fix: splash screen overlay RN avec logo jusqu au premier chargement WebView

This commit is contained in:
Mathieu 2026-05-17 12:38:20 +02:00
parent ac44033ae4
commit 8fd0568a94
2 changed files with 75 additions and 44 deletions

BIN
app/assets/movix512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View file

@ -7,7 +7,8 @@ import {
Platform,
Modal,
TouchableOpacity,
ActivityIndicator,
Image,
Animated,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import type { WebViewNavigation } from 'react-native-webview';
@ -44,6 +45,8 @@ export default function BrowserScreen() {
const [currentUrl, setCurrentUrl] = useState('');
const [dnsEnabled, setDnsEnabled] = useState(false);
const [settingsVisible, setSettingsVisible] = useState(false);
const [webViewReady, setWebViewReady] = useState(false);
const splashFade = useRef(new Animated.Value(1)).current;
const activeUrl = urlChain[mirrorIndex] ?? '';
@ -95,6 +98,15 @@ export default function BrowserScreen() {
[activeUrl, mirrorIndex, urlChain.length],
);
const onWebViewLoadEnd = useCallback(() => {
if (webViewReady) return;
Animated.timing(splashFade, {
toValue: 0,
duration: 400,
useNativeDriver: true,
}).start(() => setWebViewReady(true));
}, [webViewReady, splashFade]);
const closeSettings = useCallback(() => {
setSettingsVisible(false);
AsyncStorage.getItem('dns_enabled').then(val => {
@ -105,36 +117,34 @@ export default function BrowserScreen() {
const onRetry = useCallback(async () => {
setAllMirrorsFailed(false);
setMirrorIndex(0);
setWebViewReady(false);
splashFade.setValue(1);
await refresh();
}, [refresh]);
}, [refresh, splashFade]);
if (isLoading || !config) {
return (
<View style={[styles.container, styles.centered, { paddingTop: insets.top }]}>
<ActivityIndicator size="large" color="#8b5cf6" />
</View>
);
}
if (allMirrorsFailed) {
return (
<MirrorErrorScreen telegramUrl={config.telegramUrl} onRetry={onRetry} />
);
}
const showWebView = !isLoading && !!config && !allMirrorsFailed;
const showSplash = (!webViewReady || isLoading || !config) && !allMirrorsFailed;
return (
<View style={[styles.container, { paddingTop: insets.top }]}>
<View style={styles.webViewContainer}>
<WebViewBrowser
key={activeUrl}
ref={webViewRef}
url={activeUrl}
onNavigationStateChange={onNavigationStateChange}
onError={onWebViewError}
/>
</View>
{showWebView && (
<View style={styles.webViewContainer}>
<WebViewBrowser
key={activeUrl}
ref={webViewRef}
url={activeUrl}
onNavigationStateChange={onNavigationStateChange}
onError={onWebViewError}
onLoadEnd={onWebViewLoadEnd}
/>
</View>
)}
{!toolbarHidden && (
{allMirrorsFailed && config && (
<MirrorErrorScreen telegramUrl={config.telegramUrl} onRetry={onRetry} />
)}
{!toolbarHidden && showWebView && (
<View style={{ paddingBottom: insets.bottom }}>
<BrowserToolbar
canGoBack={canGoBack}
@ -153,23 +163,39 @@ export default function BrowserScreen() {
</View>
)}
<Modal
visible={settingsVisible}
animationType="slide"
onRequestClose={closeSettings}>
<View style={[styles.modalContainer, { paddingTop: insets.top }]}>
<View style={styles.modalHeader}>
<TouchableOpacity onPress={closeSettings} style={styles.closeButton}>
<Text style={styles.closeText}>Fermer</Text>
</TouchableOpacity>
<Text style={styles.modalTitle}>Paramètres</Text>
<View style={styles.closeButton} />
{showWebView && (
<Modal
visible={settingsVisible}
animationType="slide"
onRequestClose={closeSettings}>
<View style={[styles.modalContainer, { paddingTop: insets.top }]}>
<View style={styles.modalHeader}>
<TouchableOpacity onPress={closeSettings} style={styles.closeButton}>
<Text style={styles.closeText}>Fermer</Text>
</TouchableOpacity>
<Text style={styles.modalTitle}>Paramètres</Text>
<View style={styles.closeButton} />
</View>
<SettingsScreen />
</View>
<SettingsScreen />
</View>
</Modal>
</Modal>
)}
{navBarHidden && <MiniPill onPress={() => setSettingsVisible(true)} />}
{navBarHidden && showWebView && (
<MiniPill onPress={() => setSettingsVisible(true)} />
)}
{showSplash && (
<Animated.View
style={[StyleSheet.absoluteFillObject, styles.splash, { opacity: splashFade }]}
pointerEvents="none">
<Image
source={require('../../assets/movix512.png')}
style={styles.splashLogo}
resizeMode="contain"
/>
</Animated.View>
)}
</View>
);
}
@ -179,10 +205,6 @@ const styles = StyleSheet.create({
flex: 1,
backgroundColor: '#0a0a0a',
},
centered: {
justifyContent: 'center',
alignItems: 'center',
},
webViewContainer: {
flex: 1,
},
@ -213,4 +235,13 @@ const styles = StyleSheet.create({
fontSize: 15,
fontWeight: '500',
},
splash: {
backgroundColor: '#B5302C',
justifyContent: 'center',
alignItems: 'center',
},
splashLogo: {
width: 150,
height: 150,
},
});