89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
import * as React from "react";
|
|
import { Animated, StyleSheet, Text, View } from "react-native";
|
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
import { ToastType, useToast } from "./ToastProvider";
|
|
|
|
const fadeDuration = 300;
|
|
const tabBarHeight = 60;
|
|
|
|
export const Toast: React.FC = () => {
|
|
const insets = useSafeAreaInsets();
|
|
const { toastConfig, hideToast } = useToast();
|
|
const opacity = React.useRef(new Animated.Value(0)).current;
|
|
|
|
const fadeIn = React.useCallback(() => {
|
|
Animated.timing(opacity, {
|
|
toValue: 1,
|
|
duration: fadeDuration,
|
|
useNativeDriver: true,
|
|
}).start();
|
|
}, [opacity]);
|
|
|
|
const fadeOut = React.useCallback(() => {
|
|
Animated.timing(opacity, {
|
|
toValue: 0,
|
|
duration: fadeDuration,
|
|
useNativeDriver: true,
|
|
}).start(() => {
|
|
hideToast();
|
|
});
|
|
}, [opacity, hideToast]);
|
|
|
|
React.useEffect(() => {
|
|
if (!toastConfig) {
|
|
return;
|
|
}
|
|
|
|
fadeIn();
|
|
if (toastConfig.duration > 0) {
|
|
const timer = setTimeout(fadeOut, toastConfig.duration);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
|
|
}, [toastConfig, fadeIn, fadeOut]);
|
|
|
|
if (!toastConfig) {
|
|
return null;
|
|
}
|
|
|
|
const { type, message } = toastConfig;
|
|
|
|
const toastTypeColors: { [key in ToastType]: string } = {
|
|
[ToastType.Info]: "#17a2b8",
|
|
[ToastType.Error]: "#dc3545",
|
|
[ToastType.Success]: "#28a745",
|
|
[ToastType.Warn]: "#ffc107",
|
|
};
|
|
let backgroundColor = toastTypeColors[type];
|
|
|
|
return (
|
|
<Animated.View
|
|
style={[
|
|
styles.container,
|
|
{ bottom: insets.bottom + tabBarHeight, opacity },
|
|
]}
|
|
>
|
|
<View style={[styles.toast, { backgroundColor }]}>
|
|
<Text style={styles.message}>{message}</Text>
|
|
</View>
|
|
</Animated.View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
alignSelf: "center",
|
|
position: "absolute",
|
|
marginHorizontal: 20,
|
|
maxWidth: 480,
|
|
},
|
|
toast: {
|
|
borderRadius: 6,
|
|
padding: 16,
|
|
},
|
|
message: {
|
|
fontSize: 16,
|
|
textAlign: "center",
|
|
color: '#fff',
|
|
},
|
|
}); |