Bluesky app fork with some witchin' additions 馃挮
at main 470 lines 13 kB view raw
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}