Skip to content

Commit dd78852

Browse files
fix(mobile): raven onboarding screen has an unintended flashbang effect (#1986)
* chore: add expo-splash-screen pkg * fix: update splash screen configuration and improve app initialization
1 parent 9ecfdff commit dd78852

4 files changed

Lines changed: 94 additions & 81 deletions

File tree

apps/mobile/app.json

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
"icon": "./assets/icon.png",
99
"userInterfaceStyle": "automatic",
1010
"newArchEnabled": true,
11-
"splash": {
12-
"image": "./assets/splash.png",
13-
"resizeMode": "contain",
14-
"backgroundColor": "#000000"
15-
},
1611
"ios": {
1712
"supportsTablet": false,
1813
"appleTeamId": "W6346TTZQX",
@@ -47,6 +42,19 @@
4742
[
4843
"expo-router"
4944
],
45+
[
46+
"expo-splash-screen",
47+
{
48+
"backgroundColor": "#ffffff",
49+
"image": "./assets/splash.png",
50+
"imageWidth": 400,
51+
"resizeMode": "contain",
52+
"dark": {
53+
"backgroundColor": "#121212",
54+
"image": "./assets/splash.png"
55+
}
56+
}
57+
],
5058
[
5159
"expo-secure-store"
5260
],
@@ -87,4 +95,4 @@
8795
},
8896
"owner": "the-commit-company"
8997
}
90-
}
98+
}

apps/mobile/app/_layout.tsx

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'expo-dev-client';
2-
import { router, Slot, usePathname } from 'expo-router';
2+
import { router, Slot } from 'expo-router';
33
import { ThemeProvider } from '@react-navigation/native';
44
import "../global.css";
5-
import { useEffect } from 'react';
5+
import { useEffect, useState } from 'react';
66
import { GestureHandlerRootView } from 'react-native-gesture-handler';
77
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
88
import { setNavigationBar, themeAtom } from '@hooks/useColorScheme';
@@ -23,6 +23,9 @@ import advancedFormat from 'dayjs/plugin/advancedFormat'
2323
import relativeTime from 'dayjs/plugin/relativeTime';
2424
import { useAtom } from 'jotai';
2525
import { useColorScheme } from 'nativewind';
26+
import * as SplashScreen from 'expo-splash-screen';
27+
import * as SystemUI from 'expo-system-ui';
28+
import { Appearance } from 'react-native';
2629

2730
dayjs.extend(utc)
2831
dayjs.extend(timezone)
@@ -40,46 +43,77 @@ if (__DEV__) {
4043
]);
4144
}
4245

46+
// Prevent splash from auto-hiding before app is ready
47+
SplashScreen.preventAutoHideAsync()
48+
49+
SplashScreen.setOptions({
50+
duration: 200,
51+
fade: true,
52+
});
53+
4354
const messaging = getMessaging()
4455

4556
export default function RootLayout() {
4657

47-
// const path = usePathname()
48-
// console.log(path)
4958

50-
const { getItem } = useAsyncStorage(`default-site`)
59+
const [appIsReady, setAppIsReady] = useState(false);
60+
const { getItem } = useAsyncStorage(`default-site`);
61+
const { colorScheme, setColorScheme } = useColorScheme();
62+
const isDarkColorScheme = colorScheme === 'dark';
63+
const [theme] = useAtom(themeAtom);
64+
65+
// Set system UI background color early to prevent flash
66+
useEffect(() => {
67+
const setSystemBackground = async () => {
68+
const scheme = Appearance.getColorScheme();
69+
const bgColor = scheme === 'dark' ? '#121212' : '#ffffff';
70+
await SystemUI.setBackgroundColorAsync(bgColor);
71+
};
72+
setSystemBackground();
73+
}, []);
5174

5275

5376
useEffect(() => {
5477

5578
const onMount = async () => {
56-
// Get the defualt site from the async storage
57-
// Also check if the app was started by a notification
58-
const initialNotification = await messaging.getInitialNotification();
59-
60-
if (initialNotification) {
61-
if (initialNotification.data?.channel_id && initialNotification.data?.sitename) {
62-
setDefaultSite(initialNotification.data.sitename as string)
63-
let path = 'chat'
64-
if (initialNotification.data.is_thread) {
65-
path = 'thread'
79+
80+
try {
81+
// Get the defualt site from the async storage
82+
// Also check if the app was started by a notification
83+
const initialNotification = await messaging.getInitialNotification();
84+
85+
if (initialNotification) {
86+
if (initialNotification.data?.channel_id && initialNotification.data?.sitename) {
87+
setDefaultSite(initialNotification.data.sitename as string)
88+
let path = 'chat'
89+
if (initialNotification.data.is_thread) {
90+
path = 'thread'
91+
}
92+
router.navigate(`/${initialNotification.data.sitename}/${path}/${initialNotification.data.channel_id}`, {
93+
withAnchor: true
94+
})
95+
96+
return
6697
}
67-
router.navigate(`/${initialNotification.data.sitename}/${path}/${initialNotification.data.channel_id}`, {
68-
withAnchor: true
69-
})
98+
}
7099

71-
return
100+
// If not started by notification
101+
// On load, check if the user has a site set
102+
const defaultSite = await getItem()
103+
if (defaultSite) {
104+
router.replace(`/${defaultSite}`)
105+
} else {
106+
router.replace('/landing')
72107
}
73-
}
74108

75-
// If not started by notification
76-
// On load, check if the user has a site set
77-
const defaultSite = await getItem()
78-
if (defaultSite) {
79-
router.replace(`/${defaultSite}`)
80-
} else {
81-
router.replace('/landing')
109+
} catch (error) {
110+
console.warn('Error during app initialization:', error);
111+
router.replace('/landing');
112+
} finally {
113+
// mark app as ready regardless of success or failure
114+
setAppIsReady(true);
82115
}
116+
83117
}
84118

85119
// Handle notification open when app is in background
@@ -104,11 +138,12 @@ export default function RootLayout() {
104138
};
105139
}, []);
106140

107-
const { colorScheme, setColorScheme } = useColorScheme();
108-
109-
const isDarkColorScheme = colorScheme === 'dark'
110-
111-
const [theme] = useAtom(themeAtom);
141+
// Hide splash screen when app is ready
142+
useEffect(() => {
143+
if (appIsReady) {
144+
SplashScreen.hide();
145+
}
146+
}, [appIsReady]);
112147

113148
useEffect(() => {
114149
if (theme.state === 'hasData') {
@@ -157,4 +192,4 @@ export default function RootLayout() {
157192
</GestureHandlerRootView>
158193
</>
159194
)
160-
}
195+
}

apps/mobile/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"expo-router": "~4.0.20",
5656
"expo-secure-store": "~14.0.1",
5757
"expo-sharing": "~13.0.1",
58+
"expo-splash-screen": "~0.29.24",
5859
"expo-status-bar": "~2.0.1",
5960
"expo-system-ui": "~4.0.9",
6061
"expo-video": "~2.0.5",

yarn.lock

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,20 +1098,7 @@
10981098
"@babel/parser" "^7.27.2"
10991099
"@babel/types" "^7.27.1"
11001100

1101-
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3":
1102-
version "7.27.1"
1103-
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291"
1104-
integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==
1105-
dependencies:
1106-
"@babel/code-frame" "^7.27.1"
1107-
"@babel/generator" "^7.27.1"
1108-
"@babel/parser" "^7.27.1"
1109-
"@babel/template" "^7.27.1"
1110-
"@babel/types" "^7.27.1"
1111-
debug "^4.3.1"
1112-
globals "^11.1.0"
1113-
1114-
"@babel/traverse@^7.23.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.27.1":
1101+
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.23.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.27.1":
11151102
version "7.27.1"
11161103
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291"
11171104
integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==
@@ -6527,6 +6514,13 @@ expo-sharing@~13.0.1:
65276514
resolved "https://registry.yarnpkg.com/expo-sharing/-/expo-sharing-13.0.1.tgz#f5221ce44190a12649a6639e619d83e318c768a1"
65286515
integrity sha512-qych3Nw65wlFcnzE/gRrsdtvmdV0uF4U4qVMZBJYPG90vYyWh2QM9rp1gVu0KWOBc7N8CC2dSVYn4/BXqJy6Xw==
65296516

6517+
expo-splash-screen@~0.29.24:
6518+
version "0.29.24"
6519+
resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.29.24.tgz#4e5f6d576d3fbb37c5e3e4ee6d3f3b3ece350f75"
6520+
integrity sha512-k2rdjbb3Qeg4g104Sdz6+qXXYba8QgiuZRSxHX8IpsSYiiTU48BmCCGy12sN+O1B+sD1/+WPL4duCa1Fy6+Y4g==
6521+
dependencies:
6522+
"@expo/prebuild-config" "~8.2.0"
6523+
65306524
expo-status-bar@~2.0.1:
65316525
version "2.0.1"
65326526
resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-2.0.1.tgz#fc07726346dc30fbb68aadb0d7890b34fba42eee"
@@ -10678,16 +10672,7 @@ strict-uri-encode@^2.0.0:
1067810672
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
1067910673
integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
1068010674

10681-
"string-width-cjs@npm:string-width@^4.2.0":
10682-
version "4.2.3"
10683-
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
10684-
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
10685-
dependencies:
10686-
emoji-regex "^8.0.0"
10687-
is-fullwidth-code-point "^3.0.0"
10688-
strip-ansi "^6.0.1"
10689-
10690-
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
10675+
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
1069110676
version "4.2.3"
1069210677
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
1069310678
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -10787,7 +10772,7 @@ stringify-object@^3.3.0:
1078710772
is-obj "^1.0.1"
1078810773
is-regexp "^1.0.0"
1078910774

10790-
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
10775+
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
1079110776
version "6.0.1"
1079210777
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
1079310778
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -10801,13 +10786,6 @@ strip-ansi@^5.2.0:
1080110786
dependencies:
1080210787
ansi-regex "^4.1.0"
1080310788

10804-
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
10805-
version "6.0.1"
10806-
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
10807-
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
10808-
dependencies:
10809-
ansi-regex "^5.0.1"
10810-
1081110789
strip-ansi@^7.0.1:
1081210790
version "7.1.0"
1081310791
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -11815,16 +11793,7 @@ workbox-window@7.3.0, workbox-window@^7.3.0:
1181511793
"@types/trusted-types" "^2.0.2"
1181611794
workbox-core "7.3.0"
1181711795

11818-
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
11819-
version "7.0.0"
11820-
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
11821-
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
11822-
dependencies:
11823-
ansi-styles "^4.0.0"
11824-
string-width "^4.1.0"
11825-
strip-ansi "^6.0.0"
11826-
11827-
wrap-ansi@^7.0.0:
11796+
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
1182811797
version "7.0.0"
1182911798
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
1183011799
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==

0 commit comments

Comments
 (0)