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