forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useState} from 'react'
2import {ScrollView, View} from 'react-native'
3import {msg} from '@lingui/core/macro'
4import {useLingui} from '@lingui/react'
5
6import {usePalette} from '#/lib/hooks/usePalette'
7import {
8 type CommonNavigatorParams,
9 type NativeStackScreenProps,
10} from '#/lib/routes/types'
11import {s} from '#/lib/styles'
12import {type PaletteColorName, ThemeProvider} from '#/lib/ThemeContext'
13import {EmptyState} from '#/view/com/util/EmptyState'
14import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
15import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
16import {Button} from '#/view/com/util/forms/Button'
17import * as LoadingPlaceholder from '#/view/com/util/LoadingPlaceholder'
18import {Text} from '#/view/com/util/text/Text'
19import {ViewHeader} from '#/view/com/util/ViewHeader'
20import {ViewSelector} from '#/view/com/util/ViewSelector'
21import {HashtagWide_Stroke1_Corner0_Rounded as HashtagWideIcon} from '#/components/icons/Hashtag'
22import * as Layout from '#/components/Layout'
23import * as Toast from '#/components/Toast'
24
25const MAIN_VIEWS = ['Base', 'Controls', 'Error', 'Notifs']
26
27export const DebugScreen = ({}: NativeStackScreenProps<
28 CommonNavigatorParams,
29 'Debug'
30>) => {
31 const [colorScheme, setColorScheme] = useState<'light' | 'dark'>('light')
32 const onToggleColorScheme = () => {
33 setColorScheme(colorScheme === 'light' ? 'dark' : 'light')
34 }
35 return (
36 <ThemeProvider theme={colorScheme}>
37 <Layout.Screen>
38 <DebugInner
39 colorScheme={colorScheme}
40 onToggleColorScheme={onToggleColorScheme}
41 />
42 </Layout.Screen>
43 </ThemeProvider>
44 )
45}
46
47function DebugInner({}: {
48 colorScheme: 'light' | 'dark'
49 onToggleColorScheme: () => void
50}) {
51 const [currentView, setCurrentView] = useState<number>(0)
52 const pal = usePalette('default')
53 const {_} = useLingui()
54
55 const renderItem = (item: any) => {
56 return (
57 <View key={`view-${item.currentView}`}>
58 {item.currentView === 3 ? (
59 <NotifsView />
60 ) : item.currentView === 2 ? (
61 <ErrorView />
62 ) : item.currentView === 1 ? (
63 <ControlsView />
64 ) : (
65 <BaseView />
66 )}
67 </View>
68 )
69 }
70
71 const items = [{currentView}]
72
73 return (
74 <View style={[s.hContentRegion, pal.view]}>
75 <ViewHeader title={_(msg`Debug panel`)} />
76 <ViewSelector
77 swipeEnabled
78 sections={MAIN_VIEWS}
79 items={items}
80 renderItem={renderItem}
81 onSelectView={setCurrentView}
82 />
83 </View>
84 )
85}
86
87function Heading({label}: {label: string}) {
88 const pal = usePalette('default')
89 return (
90 <View style={[s.pt10, s.pb5]}>
91 <Text type="title-lg" style={pal.text}>
92 {label}
93 </Text>
94 </View>
95 )
96}
97
98function BaseView() {
99 return (
100 <View style={[s.pl10, s.pr10]}>
101 <Heading label="Typography" />
102 <TypographyView />
103 <Heading label="Palettes" />
104 <PaletteView palette="default" />
105 <PaletteView palette="primary" />
106 <PaletteView palette="secondary" />
107 <PaletteView palette="inverted" />
108 <PaletteView palette="error" />
109 <Heading label="Empty state" />
110 <EmptyStateView />
111 <Heading label="Loading placeholders" />
112 <LoadingPlaceholderView />
113 <View style={s.footerSpacer} />
114 </View>
115 )
116}
117
118function ControlsView() {
119 return (
120 <ScrollView style={[s.pl10, s.pr10]}>
121 <Heading label="Buttons" />
122 <ButtonsView />
123 <View style={s.footerSpacer} />
124 </ScrollView>
125 )
126}
127
128function ErrorView() {
129 return (
130 <View style={s.p10}>
131 <View style={s.mb5}>
132 <ErrorScreen
133 title="Error screen"
134 message="A major error occurred that led the entire screen to fail"
135 details="Here are some details"
136 onPressTryAgain={() => {}}
137 />
138 </View>
139 <View style={s.mb5}>
140 <ErrorMessage message="This is an error that occurred while things were being done" />
141 </View>
142 <View style={s.mb5}>
143 <ErrorMessage
144 message="This is an error that occurred while things were being done"
145 numberOfLines={1}
146 />
147 </View>
148 <View style={s.mb5}>
149 <ErrorMessage
150 message="This is an error that occurred while things were being done"
151 onPressTryAgain={() => {}}
152 />
153 </View>
154 <View style={s.mb5}>
155 <ErrorMessage
156 message="This is an error that occurred while things were being done"
157 onPressTryAgain={() => {}}
158 numberOfLines={1}
159 />
160 </View>
161 </View>
162 )
163}
164
165function NotifsView() {
166 const triggerPush = () => {
167 // TODO: implement local notification for testing
168 }
169 const triggerToast = () => {
170 Toast.show('The task has been completed')
171 }
172 const triggerToast2 = () => {
173 Toast.show('The task has been completed successfully and with no problems')
174 }
175 return (
176 <View style={s.p10}>
177 <View style={{flexDirection: 'row'}}>
178 <Button onPress={triggerPush} label="Trigger Push" />
179 <Button onPress={triggerToast} label="Trigger Toast" />
180 <Button onPress={triggerToast2} label="Trigger Toast 2" />
181 </View>
182 </View>
183 )
184}
185
186function PaletteView({palette}: {palette: PaletteColorName}) {
187 const defaultPal = usePalette('default')
188 const pal = usePalette(palette)
189 return (
190 <View style={[pal.view, pal.border, s.p10, s.mb5, {borderWidth: 1}]}>
191 <Text style={[pal.text]}>{palette} colors</Text>
192 <Text style={[pal.textLight]}>Light text</Text>
193 <Text style={[pal.link]}>Link text</Text>
194 {palette !== 'default' && (
195 <View style={[defaultPal.view]}>
196 <Text style={[pal.textInverted]}>Inverted text</Text>
197 </View>
198 )}
199 </View>
200 )
201}
202
203function TypographyView() {
204 const pal = usePalette('default')
205 return (
206 <View style={[pal.view]}>
207 <Text type="2xl-thin" style={[pal.text]}>
208 '2xl-thin' lorem ipsum dolor
209 </Text>
210 <Text type="2xl" style={[pal.text]}>
211 '2xl' lorem ipsum dolor
212 </Text>
213 <Text type="2xl-medium" style={[pal.text]}>
214 '2xl-medium' lorem ipsum dolor
215 </Text>
216 <Text type="2xl-bold" style={[pal.text]}>
217 '2xl-bold' lorem ipsum dolor
218 </Text>
219 <Text type="2xl-heavy" style={[pal.text]}>
220 '2xl-heavy' lorem ipsum dolor
221 </Text>
222 <Text type="xl-thin" style={[pal.text]}>
223 'xl-thin' lorem ipsum dolor
224 </Text>
225 <Text type="xl" style={[pal.text]}>
226 'xl' lorem ipsum dolor
227 </Text>
228 <Text type="xl-medium" style={[pal.text]}>
229 'xl-medium' lorem ipsum dolor
230 </Text>
231 <Text type="xl-bold" style={[pal.text]}>
232 'xl-bold' lorem ipsum dolor
233 </Text>
234 <Text type="xl-heavy" style={[pal.text]}>
235 'xl-heavy' lorem ipsum dolor
236 </Text>
237 <Text type="lg-thin" style={[pal.text]}>
238 'lg-thin' lorem ipsum dolor
239 </Text>
240 <Text type="lg" style={[pal.text]}>
241 'lg' lorem ipsum dolor
242 </Text>
243 <Text type="lg-medium" style={[pal.text]}>
244 'lg-medium' lorem ipsum dolor
245 </Text>
246 <Text type="lg-bold" style={[pal.text]}>
247 'lg-bold' lorem ipsum dolor
248 </Text>
249 <Text type="lg-heavy" style={[pal.text]}>
250 'lg-heavy' lorem ipsum dolor
251 </Text>
252 <Text type="md-thin" style={[pal.text]}>
253 'md-thin' lorem ipsum dolor
254 </Text>
255 <Text type="md" style={[pal.text]}>
256 'md' lorem ipsum dolor
257 </Text>
258 <Text type="md-medium" style={[pal.text]}>
259 'md-medium' lorem ipsum dolor
260 </Text>
261 <Text type="md-bold" style={[pal.text]}>
262 'md-bold' lorem ipsum dolor
263 </Text>
264 <Text type="md-heavy" style={[pal.text]}>
265 'md-heavy' lorem ipsum dolor
266 </Text>
267 <Text type="sm-thin" style={[pal.text]}>
268 'sm-thin' lorem ipsum dolor
269 </Text>
270 <Text type="sm" style={[pal.text]}>
271 'sm' lorem ipsum dolor
272 </Text>
273 <Text type="sm-medium" style={[pal.text]}>
274 'sm-medium' lorem ipsum dolor
275 </Text>
276 <Text type="sm-bold" style={[pal.text]}>
277 'sm-bold' lorem ipsum dolor
278 </Text>
279 <Text type="sm-heavy" style={[pal.text]}>
280 'sm-heavy' lorem ipsum dolor
281 </Text>
282 <Text type="xs-thin" style={[pal.text]}>
283 'xs-thin' lorem ipsum dolor
284 </Text>
285 <Text type="xs" style={[pal.text]}>
286 'xs' lorem ipsum dolor
287 </Text>
288 <Text type="xs-medium" style={[pal.text]}>
289 'xs-medium' lorem ipsum dolor
290 </Text>
291 <Text type="xs-bold" style={[pal.text]}>
292 'xs-bold' lorem ipsum dolor
293 </Text>
294 <Text type="xs-heavy" style={[pal.text]}>
295 'xs-heavy' lorem ipsum dolor
296 </Text>
297
298 <Text type="title-2xl" style={[pal.text]}>
299 'title-2xl' lorem ipsum dolor
300 </Text>
301 <Text type="title-xl" style={[pal.text]}>
302 'title-xl' lorem ipsum dolor
303 </Text>
304 <Text type="title-lg" style={[pal.text]}>
305 'title-lg' lorem ipsum dolor
306 </Text>
307 <Text type="title" style={[pal.text]}>
308 'title' lorem ipsum dolor
309 </Text>
310 <Text type="button" style={[pal.text]}>
311 Button
312 </Text>
313 <Text type="button-lg" style={[pal.text]}>
314 Button-lg
315 </Text>
316 </View>
317 )
318}
319
320function EmptyStateView() {
321 const {_} = useLingui()
322
323 return (
324 <EmptyState
325 icon={HashtagWideIcon}
326 iconSize="2xl"
327 message={_(msg`This is an empty state`)}
328 />
329 )
330}
331
332function LoadingPlaceholderView() {
333 return (
334 <>
335 <LoadingPlaceholder.PostLoadingPlaceholder />
336 <LoadingPlaceholder.NotificationLoadingPlaceholder />
337 </>
338 )
339}
340
341function ButtonsView() {
342 const defaultPal = usePalette('default')
343 const buttonStyles = {marginRight: 5}
344 return (
345 <View style={[defaultPal.view]}>
346 <View style={[{flexDirection: 'row'}, s.mb5]}>
347 <Button type="primary" label="Primary solid" style={buttonStyles} />
348 <Button type="secondary" label="Secondary solid" style={buttonStyles} />
349 </View>
350 <View style={[{flexDirection: 'row'}, s.mb5]}>
351 <Button type="default" label="Default solid" style={buttonStyles} />
352 <Button type="inverted" label="Inverted solid" style={buttonStyles} />
353 </View>
354 <View style={{flexDirection: 'row'}}>
355 <Button
356 type="primary-outline"
357 label="Primary outline"
358 style={buttonStyles}
359 />
360 <Button
361 type="secondary-outline"
362 label="Secondary outline"
363 style={buttonStyles}
364 />
365 </View>
366 <View style={{flexDirection: 'row'}}>
367 <Button
368 type="primary-light"
369 label="Primary light"
370 style={buttonStyles}
371 />
372 <Button
373 type="secondary-light"
374 label="Secondary light"
375 style={buttonStyles}
376 />
377 </View>
378 <View style={{flexDirection: 'row'}}>
379 <Button
380 type="default-light"
381 label="Default light"
382 style={buttonStyles}
383 />
384 </View>
385 </View>
386 )
387}