Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

Revert splash screen changes (#9792)

* Revert splash screen changes

This partially reverts commit 0ac5b07bfd31a6b39706ca9b6a42d2db09501e52.

* Keep android changes

authored by samuel.fm and committed by

GitHub 9ff5b2da 58f532a4

+161 -19
+9 -7
app.config.js
··· 310 310 [ 311 311 'expo-splash-screen', 312 312 { 313 - enableFullScreenImage_legacy: true, // iOS only 314 - backgroundColor: '#EEF5FF', // based on illustration 315 - image: './assets/splash/splash-mobile.png', 316 - resizeMode: 'cover', 317 - dark: { 313 + ios: { 318 314 enableFullScreenImage_legacy: true, // iOS only 319 - backgroundColor: '#446DA9', // based on illustration 320 - image: './assets/splash/splash-mobile-dark.png', 315 + backgroundColor: '#A8CCFF', // primary_200 316 + image: './assets/splash/splash.png', 321 317 resizeMode: 'cover', 318 + dark: { 319 + enableFullScreenImage_legacy: true, // iOS only 320 + backgroundColor: '#00398A', // primary_800 321 + image: './assets/splash/splash-dark.png', 322 + resizeMode: 'cover', 323 + }, 322 324 }, 323 325 android: { 324 326 backgroundColor: '#A8CCFF', // primary_200
assets/splash/splash-dark.png

This is a binary file and will not be displayed.

assets/splash/splash-mobile-dark.png assets/splash/illustration-mobile-dark.png
assets/splash/splash-mobile.png assets/splash/illustration-mobile.png
assets/splash/splash.png

This is a binary file and will not be displayed.

+149 -9
src/Splash.tsx
··· 9 9 import Animated, { 10 10 Easing, 11 11 interpolate, 12 + runOnJS, 12 13 useAnimatedStyle, 13 14 useSharedValue, 14 15 withTiming, 15 16 } from 'react-native-reanimated' 17 + import {useSafeAreaInsets} from 'react-native-safe-area-context' 18 + import Svg, {Path, type SvgProps} from 'react-native-svg' 16 19 import {Image} from 'expo-image' 17 20 import * as SplashScreen from 'expo-splash-screen' 18 21 22 + import {Logotype} from '#/view/icons/Logotype' 19 23 // @ts-ignore 20 - import splashImagePointer from '../assets/splash/splash-mobile.png' 24 + import splashImagePointer from '../assets/splash/splash.png' 21 25 // @ts-ignore 22 - import darkSplashImagePointer from '../assets/splash/splash-mobile-dark.png' 26 + import darkSplashImagePointer from '../assets/splash/splash-dark.png' 23 27 const splashImageUri = RNImage.resolveAssetSource(splashImagePointer).uri 24 28 const darkSplashImageUri = RNImage.resolveAssetSource( 25 29 darkSplashImagePointer, 26 30 ).uri 27 31 32 + export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) { 33 + const width = 1000 34 + const height = width * (67 / 64) 35 + return ( 36 + <Svg 37 + fill="none" 38 + // @ts-ignore it's fiiiiine 39 + ref={ref} 40 + viewBox="0 0 64 66" 41 + style={[{width, height}, props.style]}> 42 + <Path 43 + fill={props.fill || '#fff'} 44 + d="M13.873 3.77C21.21 9.243 29.103 20.342 32 26.3v15.732c0-.335-.13.043-.41.858-1.512 4.414-7.418 21.642-20.923 7.87-7.111-7.252-3.819-14.503 9.125-16.692-7.405 1.252-15.73-.817-18.014-8.93C1.12 22.804 0 8.431 0 6.488 0-3.237 8.579-.18 13.873 3.77ZM50.127 3.77C42.79 9.243 34.897 20.342 32 26.3v15.732c0-.335.13.043.41.858 1.512 4.414 7.418 21.642 20.923 7.87 7.111-7.252 3.819-14.503-9.125-16.692 7.405 1.252 15.73-.817 18.014-8.93C62.88 22.804 64 8.431 64 6.488 64-3.237 55.422-.18 50.127 3.77Z" 45 + /> 46 + </Svg> 47 + ) 48 + }) 49 + 28 50 type Props = { 29 51 isReady: boolean 30 52 } 31 53 32 54 export function Splash(props: React.PropsWithChildren<Props>) { 33 55 'use no memo' 56 + const insets = useSafeAreaInsets() 57 + const intro = useSharedValue(0) 58 + const outroLogo = useSharedValue(0) 59 + const outroApp = useSharedValue(0) 34 60 const outroAppOpacity = useSharedValue(0) 35 - const colorScheme = useColorScheme() 36 61 const [isAnimationComplete, setIsAnimationComplete] = React.useState(false) 37 62 const [isImageLoaded, setIsImageLoaded] = React.useState(false) 38 63 const [isLayoutReady, setIsLayoutReady] = React.useState(false) ··· 44 69 isImageLoaded && 45 70 isLayoutReady && 46 71 reduceMotion !== undefined 72 + 73 + const colorScheme = useColorScheme() 47 74 const isDarkMode = colorScheme === 'dark' 48 75 76 + const logoAnimation = useAnimatedStyle(() => { 77 + return { 78 + transform: [ 79 + { 80 + scale: interpolate(intro.get(), [0, 1], [0.8, 1], 'clamp'), 81 + }, 82 + { 83 + scale: interpolate( 84 + outroLogo.get(), 85 + [0, 0.08, 1], 86 + [1, 0.8, 500], 87 + 'clamp', 88 + ), 89 + }, 90 + ], 91 + opacity: interpolate(intro.get(), [0, 1], [0, 1], 'clamp'), 92 + } 93 + }) 94 + const bottomLogoAnimation = useAnimatedStyle(() => { 95 + return { 96 + opacity: interpolate(intro.get(), [0, 1], [0, 1], 'clamp'), 97 + } 98 + }) 99 + const reducedLogoAnimation = useAnimatedStyle(() => { 100 + return { 101 + transform: [ 102 + { 103 + scale: interpolate(intro.get(), [0, 1], [0.8, 1], 'clamp'), 104 + }, 105 + ], 106 + opacity: interpolate(intro.get(), [0, 1], [0, 1], 'clamp'), 107 + } 108 + }) 109 + 110 + const logoWrapperAnimation = useAnimatedStyle(() => { 111 + return { 112 + opacity: interpolate( 113 + outroAppOpacity.get(), 114 + [0, 0.1, 0.2, 1], 115 + [1, 1, 0, 0], 116 + 'clamp', 117 + ), 118 + } 119 + }) 120 + 49 121 const appAnimation = useAnimatedStyle(() => { 50 122 return { 123 + transform: [ 124 + { 125 + scale: interpolate(outroApp.get(), [0, 1], [1.1, 1], 'clamp'), 126 + }, 127 + ], 51 128 opacity: interpolate( 52 129 outroAppOpacity.get(), 53 130 [0, 0.1, 0.2, 1], ··· 65 142 if (isReady) { 66 143 SplashScreen.hideAsync() 67 144 .then(() => { 68 - outroAppOpacity.set(() => 69 - withTiming(1, { 70 - duration: 1200, 71 - easing: Easing.in(Easing.cubic), 72 - }), 145 + intro.set(() => 146 + withTiming( 147 + 1, 148 + {duration: 400, easing: Easing.out(Easing.cubic)}, 149 + async () => { 150 + // set these values to check animation at specific point 151 + outroLogo.set(() => 152 + withTiming( 153 + 1, 154 + {duration: 1200, easing: Easing.in(Easing.cubic)}, 155 + () => { 156 + runOnJS(onFinish)() 157 + }, 158 + ), 159 + ) 160 + outroApp.set(() => 161 + withTiming(1, { 162 + duration: 1200, 163 + easing: Easing.inOut(Easing.cubic), 164 + }), 165 + ) 166 + outroAppOpacity.set(() => 167 + withTiming(1, { 168 + duration: 1200, 169 + easing: Easing.in(Easing.cubic), 170 + }), 171 + ) 172 + }, 173 + ), 73 174 ) 74 175 }) 75 176 .catch(() => {}) 76 177 } 77 - }, [onFinish, outroAppOpacity, isReady]) 178 + }, [onFinish, intro, outroLogo, outroApp, outroAppOpacity, isReady]) 78 179 79 180 useEffect(() => { 80 181 AccessibilityInfo.isReduceMotionEnabled().then(setReduceMotion) 81 182 }, []) 82 183 184 + const logoAnimations = 185 + reduceMotion === true ? reducedLogoAnimation : logoAnimation 186 + // special off-spec color for dark mode 187 + const logoBg = isDarkMode ? '#0F1824' : '#fff' 188 + 83 189 return ( 84 190 <View style={{flex: 1}} onLayout={onLayout}> 85 191 {!isAnimationComplete && ( ··· 90 196 source={{uri: isDarkMode ? darkSplashImageUri : splashImageUri}} 91 197 style={StyleSheet.absoluteFillObject} 92 198 /> 199 + 200 + <Animated.View 201 + style={[ 202 + bottomLogoAnimation, 203 + { 204 + position: 'absolute', 205 + bottom: insets.bottom + 40, 206 + left: 0, 207 + right: 0, 208 + alignItems: 'center', 209 + justifyContent: 'center', 210 + opacity: 0, 211 + }, 212 + ]}> 213 + <Logotype fill="#fff" width={90} /> 214 + </Animated.View> 93 215 </View> 94 216 )} 95 217 ··· 98 220 <Animated.View style={[{flex: 1}, appAnimation]}> 99 221 {props.children} 100 222 </Animated.View> 223 + 224 + {!isAnimationComplete && ( 225 + <Animated.View 226 + style={[ 227 + StyleSheet.absoluteFillObject, 228 + logoWrapperAnimation, 229 + { 230 + flex: 1, 231 + justifyContent: 'center', 232 + alignItems: 'center', 233 + transform: [{translateY: -(insets.top / 2)}, {scale: 0.1}], // scale from 1000px to 100px 234 + }, 235 + ]}> 236 + <Animated.View style={[logoAnimations]}> 237 + <Logo fill={logoBg} /> 238 + </Animated.View> 239 + </Animated.View> 240 + )} 101 241 </> 102 242 )} 103 243 </View>
+3 -3
src/view/com/auth/SplashScreen.tsx
··· 11 11 import {atoms as a, useTheme} from '#/alf' 12 12 import {Button, ButtonText} from '#/components/Button' 13 13 // @ts-ignore 14 - import splashImagePointer from '../../../../assets/splash/splash-mobile.png' 14 + import splashImagePointer from '../../../../assets/splash/illustration-mobile.png' 15 15 // @ts-ignore 16 - import darkSplashImagePointer from '../../../../assets/splash/splash-mobile-dark.png' 16 + import darkSplashImagePointer from '../../../../assets/splash/illustration-mobile-dark.png' 17 17 const splashImageUri = RNImage.resolveAssetSource(splashImagePointer).uri 18 18 const darkSplashImageUri = RNImage.resolveAssetSource( 19 19 darkSplashImagePointer, ··· 78 78 79 79 <View 80 80 testID="signinOrCreateAccount" 81 - style={[a.px_xl, a.gap_md, a.pb_sm]}> 81 + style={[a.px_5xl, a.gap_md, a.pb_sm]}> 82 82 <View 83 83 style={[ 84 84 t.atoms.shadow_md,