mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {memo} from 'react'
2import {StyleProp, View, ViewStyle} from 'react-native'
3import {msg, Trans} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5
6import {cleanError} from 'lib/strings/errors'
7import {CenteredView} from 'view/com/util/Views'
8import {atoms as a, flatten, useBreakpoints, useTheme} from '#/alf'
9import {Button, ButtonText} from '#/components/Button'
10import {Error} from '#/components/Error'
11import {Loader} from '#/components/Loader'
12import {Text} from '#/components/Typography'
13
14export function ListFooter({
15 isFetchingNextPage,
16 hasNextPage,
17 error,
18 onRetry,
19 height,
20 style,
21 showEndMessage = false,
22 endMessageText,
23}: {
24 isFetchingNextPage?: boolean
25 hasNextPage?: boolean
26 error?: string
27 onRetry?: () => Promise<unknown>
28 height?: number
29 style?: StyleProp<ViewStyle>
30 showEndMessage?: boolean
31 endMessageText?: string
32}) {
33 const t = useTheme()
34
35 return (
36 <View
37 style={[
38 a.w_full,
39 a.align_center,
40 a.border_t,
41 a.pb_lg,
42 t.atoms.border_contrast_low,
43 {height: height ?? 180, paddingTop: 30},
44 flatten(style),
45 ]}>
46 {isFetchingNextPage ? (
47 <Loader size="xl" />
48 ) : error ? (
49 <ListFooterMaybeError error={error} onRetry={onRetry} />
50 ) : !hasNextPage && showEndMessage ? (
51 <Text style={[a.text_sm, t.atoms.text_contrast_low]}>
52 {endMessageText ?? <Trans>You have reached the end</Trans>}
53 </Text>
54 ) : null}
55 </View>
56 )
57}
58
59function ListFooterMaybeError({
60 error,
61 onRetry,
62}: {
63 error?: string
64 onRetry?: () => Promise<unknown>
65}) {
66 const t = useTheme()
67 const {_} = useLingui()
68
69 if (!error) return null
70
71 return (
72 <View style={[a.w_full, a.px_lg]}>
73 <View
74 style={[
75 a.flex_row,
76 a.gap_md,
77 a.p_md,
78 a.rounded_sm,
79 a.align_center,
80 t.atoms.bg_contrast_25,
81 ]}>
82 <Text
83 style={[a.flex_1, a.text_sm, t.atoms.text_contrast_medium]}
84 numberOfLines={2}>
85 {error ? (
86 cleanError(error)
87 ) : (
88 <Trans>Oops, something went wrong!</Trans>
89 )}
90 </Text>
91 <Button
92 variant="gradient"
93 label={_(msg`Press to retry`)}
94 style={[
95 a.align_center,
96 a.justify_center,
97 a.rounded_sm,
98 a.overflow_hidden,
99 a.px_md,
100 a.py_sm,
101 ]}
102 onPress={onRetry}>
103 <ButtonText>
104 <Trans>Retry</Trans>
105 </ButtonText>
106 </Button>
107 </View>
108 </View>
109 )
110}
111
112export function ListHeaderDesktop({
113 title,
114 subtitle,
115}: {
116 title: string
117 subtitle?: string
118}) {
119 const {gtTablet} = useBreakpoints()
120 const t = useTheme()
121
122 if (!gtTablet) return null
123
124 return (
125 <View style={[a.w_full, a.py_lg, a.px_xl, a.gap_xs]}>
126 <Text style={[a.text_3xl, a.font_bold]}>{title}</Text>
127 {subtitle ? (
128 <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
129 {subtitle}
130 </Text>
131 ) : undefined}
132 </View>
133 )
134}
135
136let ListMaybePlaceholder = ({
137 isLoading,
138 noEmpty,
139 isError,
140 emptyTitle,
141 emptyMessage,
142 errorTitle,
143 errorMessage,
144 emptyType = 'page',
145 onRetry,
146 onGoBack,
147 hideBackButton,
148 sideBorders,
149 topBorder = true,
150}: {
151 isLoading: boolean
152 noEmpty?: boolean
153 isError?: boolean
154 emptyTitle?: string
155 emptyMessage?: string
156 errorTitle?: string
157 errorMessage?: string
158 emptyType?: 'page' | 'results'
159 onRetry?: () => Promise<unknown>
160 onGoBack?: () => void
161 hideBackButton?: boolean
162 sideBorders?: boolean
163 topBorder?: boolean
164}): React.ReactNode => {
165 const t = useTheme()
166 const {_} = useLingui()
167 const {gtMobile, gtTablet} = useBreakpoints()
168
169 if (isLoading) {
170 return (
171 <CenteredView
172 style={[
173 a.flex_1,
174 a.align_center,
175 !gtMobile ? a.justify_between : a.gap_5xl,
176 t.atoms.border_contrast_low,
177 {paddingTop: 175, paddingBottom: 110},
178 ]}
179 sideBorders={sideBorders ?? gtMobile}
180 topBorder={topBorder && !gtTablet}>
181 <View style={[a.w_full, a.align_center, {top: 100}]}>
182 <Loader size="xl" />
183 </View>
184 </CenteredView>
185 )
186 }
187
188 if (isError) {
189 return (
190 <Error
191 title={errorTitle ?? _(msg`Oops!`)}
192 message={errorMessage ?? _(`Something went wrong!`)}
193 onRetry={onRetry}
194 onGoBack={onGoBack}
195 sideBorders={sideBorders}
196 hideBackButton={hideBackButton}
197 />
198 )
199 }
200
201 if (!noEmpty) {
202 return (
203 <Error
204 title={
205 emptyTitle ??
206 (emptyType === 'results'
207 ? _(msg`No results found`)
208 : _(msg`Page not found`))
209 }
210 message={
211 emptyMessage ??
212 _(msg`We're sorry! We can't find the page you were looking for.`)
213 }
214 onRetry={onRetry}
215 onGoBack={onGoBack}
216 hideBackButton={hideBackButton}
217 sideBorders={sideBorders}
218 />
219 )
220 }
221
222 return null
223}
224ListMaybePlaceholder = memo(ListMaybePlaceholder)
225export {ListMaybePlaceholder}