-
Notifications
You must be signed in to change notification settings - Fork 570
/
LoadFailureView.tsx
116 lines (108 loc) · 3.42 KB
/
LoadFailureView.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { ReloadIcon, Flex, Box, BoxProps, useColor, Text, Touchable } from "@artsy/palette-mobile"
import * as Sentry from "@sentry/react-native"
import { GlobalStore } from "app/store/GlobalStore"
import { useDevToggle } from "app/utils/hooks/useDevToggle"
import { useIsStaging } from "app/utils/hooks/useIsStaging"
import { debounce } from "lodash"
import { useEffect, useRef, useState } from "react"
import { Animated, Easing } from "react-native"
import { JustifyContentValue } from "./Bidding/Elements/types"
interface LoadFailureViewProps {
error?: Error
onRetry?: () => void
justifyContent?: JustifyContentValue
}
export const LoadFailureView: React.FC<LoadFailureViewProps & BoxProps> = ({
error,
onRetry,
...restProps
}) => {
const color = useColor()
const spinAnimation = useRef(new Animated.Value(0)).current
const [isAnimating, setIsAnimating] = useState(false)
const userId = GlobalStore.useAppState((state) => state.auth.userID)
const activeTab = GlobalStore.useAppState((state) => state.bottomTabs.sessionState.selectedTab)
const showErrorInLoadFailureViewToggle = useDevToggle("DTShowErrorInLoadFailureView")
const isStaging = useIsStaging()
const showErrorMessage = __DEV__ || isStaging || showErrorInLoadFailureViewToggle
const trackLoadFailureView = (error: Error | undefined) => {
const shouldTrackError = !__DEV__ && !isStaging
if (shouldTrackError) {
Sentry.withScope((scope) => {
scope.setExtra("user-id", userId)
if (error) {
scope.setExtra("error", error)
}
Sentry.captureMessage("Unable to load in tab: " + activeTab, "error")
})
}
}
useEffect(() => {
trackLoadFailureView(error)
}, [error])
const playAnimation = () => {
setIsAnimating(true)
Animated.loop(
Animated.timing(spinAnimation, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
easing: Easing.linear,
})
).start()
}
return (
<Flex flex={1} alignItems="center" justifyContent="center" {...restProps}>
<Text variant="lg-display">Unable to load</Text>
<Text variant="sm-display" mb={1}>
Please try again
</Text>
{!!isStaging && <Box mb={1} border={2} width={200} borderColor="devpurple" />}
{!!onRetry && (
<Touchable
onPress={debounce(() => {
if (!isAnimating) {
playAnimation()
}
onRetry?.()
})}
underlayColor={color("black5")}
haptic
style={{
height: 40,
width: 40,
borderRadius: 20,
borderColor: color("black10"),
borderWidth: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Animated.View
style={{
height: 40,
width: 40,
justifyContent: "center",
alignItems: "center",
transform: [
{
rotate: spinAnimation.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "360deg"],
}),
},
],
}}
>
<ReloadIcon height={25} width={25} />
</Animated.View>
</Touchable>
)}
{!!showErrorMessage && (
<Flex m={2}>
<Text>Error: {error?.message}</Text>
</Flex>
)}
</Flex>
)
}