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