diff --git a/app.config.js b/app.config.js
index f2403edd47..4f2780feb1 100644
--- a/app.config.js
+++ b/app.config.js
@@ -66,6 +66,12 @@ module.exports = function () {
'Used for profile pictures, posts, and other kinds of content',
},
associatedDomains: ['applinks:bsky.app', 'applinks:staging.bsky.app'],
+ splash: {
+ dark: {
+ image: './assets/splash-dark.png',
+ backgroundColor: '#001429',
+ },
+ },
},
androidStatusBar: {
barStyle: 'dark-content',
@@ -95,6 +101,12 @@ module.exports = function () {
category: ['BROWSABLE', 'DEFAULT'],
},
],
+ splash: {
+ dark: {
+ image: './assets/splash-dark.png',
+ backgroundColor: '#001429',
+ },
+ },
},
web: {
favicon: './assets/favicon.png',
diff --git a/assets/splash-dark.png b/assets/splash-dark.png
new file mode 100644
index 0000000000..6425bf28a1
Binary files /dev/null and b/assets/splash-dark.png differ
diff --git a/src/Splash.tsx b/src/Splash.tsx
index d3b21dd630..bb2c7a1757 100644
--- a/src/Splash.tsx
+++ b/src/Splash.tsx
@@ -1,5 +1,11 @@
import React, {useCallback, useEffect} from 'react'
-import {View, StyleSheet, Image as RNImage} from 'react-native'
+import {
+ View,
+ StyleSheet,
+ Image as RNImage,
+ AccessibilityInfo,
+ useColorScheme,
+} from 'react-native'
import * as SplashScreen from 'expo-splash-screen'
import {Image} from 'expo-image'
import Animated, {
@@ -15,10 +21,17 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
import Svg, {Path, SvgProps} from 'react-native-svg'
import {isAndroid} from '#/platform/detection'
+import {useColorMode} from 'state/shell'
+import {colors} from '#/lib/styles'
// @ts-ignore
import splashImagePointer from '../assets/splash.png'
+// @ts-ignore
+import darkSplashImagePointer from '../assets/splash-dark.png'
const splashImageUri = RNImage.resolveAssetSource(splashImagePointer).uri
+const darkSplashImageUri = RNImage.resolveAssetSource(
+ darkSplashImagePointer,
+).uri
export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
const width = 1000
@@ -29,9 +42,9 @@ export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
// @ts-ignore it's fiiiiine
ref={ref}
viewBox="0 0 64 66"
- style={{width, height}}>
+ style={[{width, height}, props.style]}>
@@ -53,7 +66,19 @@ export function Splash(props: React.PropsWithChildren) {
const [isAnimationComplete, setIsAnimationComplete] = React.useState(false)
const [isImageLoaded, setIsImageLoaded] = React.useState(false)
const [isLayoutReady, setIsLayoutReady] = React.useState(false)
- const isReady = props.isReady && isImageLoaded && isLayoutReady
+ const [reduceMotion, setReduceMotion] = React.useState(
+ false,
+ )
+ const isReady =
+ props.isReady &&
+ isImageLoaded &&
+ isLayoutReady &&
+ reduceMotion !== undefined
+
+ const colorMode = useColorMode()
+ const colorScheme = useColorScheme()
+ const themeName = colorMode === 'system' ? colorScheme : colorMode
+ const isDarkMode = themeName === 'dark'
const logoAnimation = useAnimatedStyle(() => {
return {
@@ -73,6 +98,17 @@ export function Splash(props: React.PropsWithChildren) {
opacity: interpolate(intro.value, [0, 1], [0, 1], 'clamp'),
}
})
+ const reducedLogoAnimation = useAnimatedStyle(() => {
+ return {
+ transform: [
+ {
+ scale: interpolate(intro.value, [0, 1], [0.8, 1], 'clamp'),
+ },
+ ],
+ opacity: interpolate(intro.value, [0, 1], [0, 1], 'clamp'),
+ }
+ })
+
const logoWrapperAnimation = useAnimatedStyle(() => {
return {
opacity: interpolate(
@@ -137,71 +173,85 @@ export function Splash(props: React.PropsWithChildren) {
}
}, [onFinish, intro, outroLogo, outroApp, outroAppOpacity, isReady])
+ useEffect(() => {
+ AccessibilityInfo.isReduceMotionEnabled().then(setReduceMotion)
+ }, [])
+
+ const logoAnimations =
+ reduceMotion === true ? reducedLogoAnimation : logoAnimation
+
return (
{!isAnimationComplete && (
)}
- {isAndroid ? (
- // Use a simple fade on older versions of android (work around a bug)
- <>
-
- {props.children}
-
+ {isReady &&
+ (isAndroid || reduceMotion === true ? (
+ // Use a simple fade on older versions of android (work around a bug)
+ <>
+
+ {props.children}
+
- {!isAnimationComplete && (
-
-
+ {!isAnimationComplete && (
+
+
+
+ )}
+ >
+ ) : (
+
+
+
+ }>
+ {!isAnimationComplete && (
+
+ )}
+
+ {props.children}
- )}
- >
- ) : (
-
-
-
- }>
- {!isAnimationComplete && (
-
- )}
-
- {props.children}
-
-
- )}
+
+ ))}
)
}