Bluesky app fork with some witchin' additions 💫

Remove top padding from shell, move down into individual screens (#5548)

authored by samuel.fm and committed by GitHub 2d884634 0f400139

+13 -13
src/Navigation.tsx
··· 17 17 18 18 import {timeout} from '#/lib/async/timeout' 19 19 import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle' 20 - import {usePalette} from '#/lib/hooks/usePalette' 21 20 import {useWebScrollRestoration} from '#/lib/hooks/useWebScrollRestoration' 22 21 import {buildStateObject} from '#/lib/routes/helpers' 23 22 import { ··· 93 92 StarterPackScreenShort, 94 93 } from '#/screens/StarterPack/StarterPackScreen' 95 94 import {Wizard} from '#/screens/StarterPack/Wizard' 95 + import {useTheme} from '#/alf' 96 96 import {router} from '#/routes' 97 97 import {Referrer} from '../modules/expo-bluesky-swiss-army' 98 98 ··· 412 412 } 413 413 414 414 function HomeTabNavigator() { 415 - const pal = usePalette('default') 415 + const t = useTheme() 416 416 417 417 return ( 418 418 <HomeTab.Navigator ··· 422 422 gestureEnabled: true, 423 423 fullScreenGestureEnabled: true, 424 424 headerShown: false, 425 - contentStyle: pal.view, 425 + contentStyle: t.atoms.bg, 426 426 }}> 427 427 <HomeTab.Screen name="Home" getComponent={() => HomeScreen} /> 428 428 <HomeTab.Screen name="Start" getComponent={() => HomeScreen} /> ··· 432 432 } 433 433 434 434 function SearchTabNavigator() { 435 - const pal = usePalette('default') 435 + const t = useTheme() 436 436 return ( 437 437 <SearchTab.Navigator 438 438 screenOptions={{ ··· 441 441 gestureEnabled: true, 442 442 fullScreenGestureEnabled: true, 443 443 headerShown: false, 444 - contentStyle: pal.view, 444 + contentStyle: t.atoms.bg, 445 445 }}> 446 446 <SearchTab.Screen name="Search" getComponent={() => SearchScreen} /> 447 447 {commonScreens(SearchTab as typeof HomeTab)} ··· 450 450 } 451 451 452 452 function NotificationsTabNavigator() { 453 - const pal = usePalette('default') 453 + const t = useTheme() 454 454 return ( 455 455 <NotificationsTab.Navigator 456 456 screenOptions={{ ··· 459 459 gestureEnabled: true, 460 460 fullScreenGestureEnabled: true, 461 461 headerShown: false, 462 - contentStyle: pal.view, 462 + contentStyle: t.atoms.bg, 463 463 }}> 464 464 <NotificationsTab.Screen 465 465 name="Notifications" ··· 472 472 } 473 473 474 474 function MyProfileTabNavigator() { 475 - const pal = usePalette('default') 475 + const t = useTheme() 476 476 return ( 477 477 <MyProfileTab.Navigator 478 478 screenOptions={{ ··· 481 481 gestureEnabled: true, 482 482 fullScreenGestureEnabled: true, 483 483 headerShown: false, 484 - contentStyle: pal.view, 484 + contentStyle: t.atoms.bg, 485 485 }}> 486 486 <MyProfileTab.Screen 487 487 // @ts-ignore // TODO: fix this broken type in ProfileScreen ··· 498 498 } 499 499 500 500 function MessagesTabNavigator() { 501 - const pal = usePalette('default') 501 + const t = useTheme() 502 502 return ( 503 503 <MessagesTab.Navigator 504 504 screenOptions={{ ··· 507 507 gestureEnabled: true, 508 508 fullScreenGestureEnabled: true, 509 509 headerShown: false, 510 - contentStyle: pal.view, 510 + contentStyle: t.atoms.bg, 511 511 }}> 512 512 <MessagesTab.Screen 513 513 name="Messages" ··· 527 527 * in a single ("flat") stack. 528 528 */ 529 529 const FlatNavigator = () => { 530 - const pal = usePalette('default') 530 + const t = useTheme() 531 531 const numUnread = useUnreadNotifications() 532 532 const screenListeners = useWebScrollRestoration() 533 533 const title = (page: MessageDescriptor) => bskyTitle(i18n._(page), numUnread) ··· 541 541 gestureEnabled: true, 542 542 fullScreenGestureEnabled: true, 543 543 headerShown: false, 544 - contentStyle: pal.view, 544 + contentStyle: t.atoms.bg, 545 545 }}> 546 546 <Flat.Screen 547 547 name="Home"
+41
src/components/Layout.tsx
··· 1 + import React from 'react' 2 + import {View, ViewStyle} from 'react-native' 3 + import {StyleProp} from 'react-native' 4 + import {useSafeAreaInsets} from 'react-native-safe-area-context' 5 + 6 + import {atoms as a} from '#/alf' 7 + 8 + // Every screen should have a Layout component wrapping it. 9 + // This component provides a default padding for the top of the screen. 10 + // This allows certain screens to avoid the top padding if they want to. 11 + // 12 + // In a future PR I will add a unified header component to this file and 13 + // things like a preconfigured scrollview. 14 + 15 + /** 16 + * Every screen should have a Layout.Screen component wrapping it. 17 + * This component provides a default padding for the top of the screen 18 + * and height/minHeight 19 + */ 20 + let Screen = ({ 21 + disableTopPadding, 22 + style, 23 + ...props 24 + }: React.ComponentProps<typeof View> & { 25 + disableTopPadding?: boolean 26 + style?: StyleProp<ViewStyle> 27 + }): React.ReactNode => { 28 + const {top} = useSafeAreaInsets() 29 + return ( 30 + <View 31 + style={[ 32 + {paddingTop: disableTopPadding ? 0 : top}, 33 + a.util_screen_outer, 34 + style, 35 + ]} 36 + {...props} 37 + /> 38 + ) 39 + } 40 + Screen = React.memo(Screen) 41 + export {Screen}
+101 -98
src/screens/E2E/SharedPreferencesTesterScreen.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 3 4 - import {ScrollView} from 'view/com/util/Views' 4 + import {ScrollView} from '#/view/com/util/Views' 5 5 import {atoms as a} from '#/alf' 6 6 import {Button, ButtonText} from '#/components/Button' 7 + import * as Layout from '#/components/Layout' 7 8 import {Text} from '#/components/Typography' 8 9 import {SharedPrefs} from '../../../modules/expo-bluesky-swiss-army' 9 10 ··· 11 12 const [currentTestOutput, setCurrentTestOutput] = React.useState<string>('') 12 13 13 14 return ( 14 - <ScrollView contentContainerStyle={{backgroundColor: 'red'}}> 15 - <View style={[a.flex_1]}> 16 - <View> 17 - <Text testID="testOutput">{currentTestOutput}</Text> 15 + <Layout.Screen> 16 + <ScrollView contentContainerStyle={{backgroundColor: 'red'}}> 17 + <View style={[a.flex_1]}> 18 + <View> 19 + <Text testID="testOutput">{currentTestOutput}</Text> 20 + </View> 21 + <View style={[a.flex_wrap]}> 22 + <Button 23 + label="btn" 24 + testID="setStringBtn" 25 + style={[a.self_center]} 26 + variant="solid" 27 + color="primary" 28 + size="small" 29 + onPress={async () => { 30 + SharedPrefs.removeValue('testerString') 31 + SharedPrefs.setValue('testerString', 'Hello') 32 + const str = SharedPrefs.getString('testerString') 33 + console.log(JSON.stringify(str)) 34 + setCurrentTestOutput(`${str}`) 35 + }}> 36 + <ButtonText>Set String</ButtonText> 37 + </Button> 38 + <Button 39 + label="btn" 40 + testID="removeStringBtn" 41 + style={[a.self_center]} 42 + variant="solid" 43 + color="primary" 44 + size="small" 45 + onPress={async () => { 46 + SharedPrefs.removeValue('testerString') 47 + const str = SharedPrefs.getString('testerString') 48 + setCurrentTestOutput(`${str}`) 49 + }}> 50 + <ButtonText>Remove String</ButtonText> 51 + </Button> 52 + <Button 53 + label="btn" 54 + testID="setBoolBtn" 55 + style={[a.self_center]} 56 + variant="solid" 57 + color="primary" 58 + size="small" 59 + onPress={async () => { 60 + SharedPrefs.removeValue('testerBool') 61 + SharedPrefs.setValue('testerBool', true) 62 + const bool = SharedPrefs.getBool('testerBool') 63 + setCurrentTestOutput(`${bool}`) 64 + }}> 65 + <ButtonText>Set Bool</ButtonText> 66 + </Button> 67 + <Button 68 + label="btn" 69 + testID="setNumberBtn" 70 + style={[a.self_center]} 71 + variant="solid" 72 + color="primary" 73 + size="small" 74 + onPress={async () => { 75 + SharedPrefs.removeValue('testerNumber') 76 + SharedPrefs.setValue('testerNumber', 123) 77 + const num = SharedPrefs.getNumber('testerNumber') 78 + setCurrentTestOutput(`${num}`) 79 + }}> 80 + <ButtonText>Set Number</ButtonText> 81 + </Button> 82 + <Button 83 + label="btn" 84 + testID="addToSetBtn" 85 + style={[a.self_center]} 86 + variant="solid" 87 + color="primary" 88 + size="small" 89 + onPress={async () => { 90 + SharedPrefs.removeFromSet('testerSet', 'Hello!') 91 + SharedPrefs.addToSet('testerSet', 'Hello!') 92 + const contains = SharedPrefs.setContains('testerSet', 'Hello!') 93 + setCurrentTestOutput(`${contains}`) 94 + }}> 95 + <ButtonText>Add to Set</ButtonText> 96 + </Button> 97 + <Button 98 + label="btn" 99 + testID="removeFromSetBtn" 100 + style={[a.self_center]} 101 + variant="solid" 102 + color="primary" 103 + size="small" 104 + onPress={async () => { 105 + SharedPrefs.removeFromSet('testerSet', 'Hello!') 106 + const contains = SharedPrefs.setContains('testerSet', 'Hello!') 107 + setCurrentTestOutput(`${contains}`) 108 + }}> 109 + <ButtonText>Remove from Set</ButtonText> 110 + </Button> 111 + </View> 18 112 </View> 19 - <View style={[a.flex_wrap]}> 20 - <Button 21 - label="btn" 22 - testID="setStringBtn" 23 - style={[a.self_center]} 24 - variant="solid" 25 - color="primary" 26 - size="small" 27 - onPress={async () => { 28 - SharedPrefs.removeValue('testerString') 29 - SharedPrefs.setValue('testerString', 'Hello') 30 - const str = SharedPrefs.getString('testerString') 31 - console.log(JSON.stringify(str)) 32 - setCurrentTestOutput(`${str}`) 33 - }}> 34 - <ButtonText>Set String</ButtonText> 35 - </Button> 36 - <Button 37 - label="btn" 38 - testID="removeStringBtn" 39 - style={[a.self_center]} 40 - variant="solid" 41 - color="primary" 42 - size="small" 43 - onPress={async () => { 44 - SharedPrefs.removeValue('testerString') 45 - const str = SharedPrefs.getString('testerString') 46 - setCurrentTestOutput(`${str}`) 47 - }}> 48 - <ButtonText>Remove String</ButtonText> 49 - </Button> 50 - <Button 51 - label="btn" 52 - testID="setBoolBtn" 53 - style={[a.self_center]} 54 - variant="solid" 55 - color="primary" 56 - size="small" 57 - onPress={async () => { 58 - SharedPrefs.removeValue('testerBool') 59 - SharedPrefs.setValue('testerBool', true) 60 - const bool = SharedPrefs.getBool('testerBool') 61 - setCurrentTestOutput(`${bool}`) 62 - }}> 63 - <ButtonText>Set Bool</ButtonText> 64 - </Button> 65 - <Button 66 - label="btn" 67 - testID="setNumberBtn" 68 - style={[a.self_center]} 69 - variant="solid" 70 - color="primary" 71 - size="small" 72 - onPress={async () => { 73 - SharedPrefs.removeValue('testerNumber') 74 - SharedPrefs.setValue('testerNumber', 123) 75 - const num = SharedPrefs.getNumber('testerNumber') 76 - setCurrentTestOutput(`${num}`) 77 - }}> 78 - <ButtonText>Set Number</ButtonText> 79 - </Button> 80 - <Button 81 - label="btn" 82 - testID="addToSetBtn" 83 - style={[a.self_center]} 84 - variant="solid" 85 - color="primary" 86 - size="small" 87 - onPress={async () => { 88 - SharedPrefs.removeFromSet('testerSet', 'Hello!') 89 - SharedPrefs.addToSet('testerSet', 'Hello!') 90 - const contains = SharedPrefs.setContains('testerSet', 'Hello!') 91 - setCurrentTestOutput(`${contains}`) 92 - }}> 93 - <ButtonText>Add to Set</ButtonText> 94 - </Button> 95 - <Button 96 - label="btn" 97 - testID="removeFromSetBtn" 98 - style={[a.self_center]} 99 - variant="solid" 100 - color="primary" 101 - size="small" 102 - onPress={async () => { 103 - SharedPrefs.removeFromSet('testerSet', 'Hello!') 104 - const contains = SharedPrefs.setContains('testerSet', 'Hello!') 105 - setCurrentTestOutput(`${contains}`) 106 - }}> 107 - <ButtonText>Remove from Set</ButtonText> 108 - </Button> 109 - </View> 110 - </View> 111 - </ScrollView> 113 + </ScrollView> 114 + </Layout.Screen> 112 115 ) 113 116 }
+16 -15
src/screens/Hashtag.tsx
··· 6 6 import {useFocusEffect} from '@react-navigation/native' 7 7 import {NativeStackScreenProps} from '@react-navigation/native-stack' 8 8 9 - import {HITSLOP_10} from 'lib/constants' 10 - import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' 11 - import {CommonNavigatorParams} from 'lib/routes/types' 12 - import {shareUrl} from 'lib/sharing' 13 - import {cleanError} from 'lib/strings/errors' 14 - import {sanitizeHandle} from 'lib/strings/handles' 15 - import {enforceLen} from 'lib/strings/helpers' 16 - import {isNative, isWeb} from 'platform/detection' 17 - import {useSearchPostsQuery} from 'state/queries/search-posts' 18 - import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from 'state/shell' 9 + import {HITSLOP_10} from '#/lib/constants' 10 + import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' 11 + import {CommonNavigatorParams} from '#/lib/routes/types' 12 + import {shareUrl} from '#/lib/sharing' 13 + import {cleanError} from '#/lib/strings/errors' 14 + import {sanitizeHandle} from '#/lib/strings/handles' 15 + import {enforceLen} from '#/lib/strings/helpers' 16 + import {isNative, isWeb} from '#/platform/detection' 17 + import {useSearchPostsQuery} from '#/state/queries/search-posts' 18 + import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell' 19 19 import {Pager} from '#/view/com/pager/Pager' 20 20 import {TabBar} from '#/view/com/pager/TabBar' 21 + import {Post} from '#/view/com/post/Post' 22 + import {List} from '#/view/com/util/List' 23 + import {ViewHeader} from '#/view/com/util/ViewHeader' 21 24 import {CenteredView} from '#/view/com/util/Views' 22 - import {Post} from 'view/com/post/Post' 23 - import {List} from 'view/com/util/List' 24 - import {ViewHeader} from 'view/com/util/ViewHeader' 25 25 import {ArrowOutOfBox_Stroke2_Corner0_Rounded} from '#/components/icons/ArrowOutOfBox' 26 + import * as Layout from '#/components/Layout' 26 27 import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' 27 28 28 29 const renderItem = ({item}: ListRenderItemInfo<PostView>) => { ··· 108 109 }, [_, fullTag, author, activeTab]) 109 110 110 111 return ( 111 - <> 112 + <Layout.Screen> 112 113 <CenteredView sideBorders={true}> 113 114 <ViewHeader 114 115 showOnDesktop ··· 155 156 <View key={i}>{section.component}</View> 156 157 ))} 157 158 </Pager> 158 - </> 159 + </Layout.Screen> 159 160 ) 160 161 } 161 162
+5 -4
src/screens/Messages/ChatList.tsx
··· 28 28 import {Message_Stroke2_Corner0_Rounded as Message} from '#/components/icons/Message' 29 29 import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' 30 30 import {SettingsSliderVertical_Stroke2_Corner0_Rounded as SettingsSlider} from '#/components/icons/SettingsSlider' 31 + import * as Layout from '#/components/Layout' 31 32 import {Link} from '#/components/Link' 32 33 import {ListFooter} from '#/components/Lists' 33 34 import {Loader} from '#/components/Loader' ··· 149 150 150 151 if (conversations.length < 1) { 151 152 return ( 152 - <View style={a.flex_1}> 153 + <Layout.Screen> 153 154 <CenteredView sideBorders={gtMobile} style={[a.h_full_vh]}> 154 155 {gtMobile ? ( 155 156 <DesktopHeader ··· 231 232 {!isLoading && !isError && ( 232 233 <NewChat onNewChat={onNewChat} control={newChatControl} /> 233 234 )} 234 - </View> 235 + </Layout.Screen> 235 236 ) 236 237 } 237 238 238 239 return ( 239 - <View style={a.flex_1}> 240 + <Layout.Screen testID="messagesScreen"> 240 241 {!gtMobile && ( 241 242 <ViewHeader 242 243 title={_(msg`Messages`)} ··· 276 277 // @ts-ignore our .web version only -sfn 277 278 desktopFixedHeight 278 279 /> 279 - </View> 280 + </Layout.Screen> 280 281 ) 281 282 } 282 283
+8 -5
src/screens/Messages/Conversation.tsx
··· 18 18 import {useSetMinimalShellMode} from '#/state/shell' 19 19 import {CenteredView} from '#/view/com/util/Views' 20 20 import {MessagesList} from '#/screens/Messages/components/MessagesList' 21 - import {atoms as a, useBreakpoints, useTheme} from '#/alf' 21 + import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' 22 22 import {MessagesListBlockedFooter} from '#/components/dms/MessagesListBlockedFooter' 23 23 import {MessagesListHeader} from '#/components/dms/MessagesListHeader' 24 24 import {Error} from '#/components/Error' 25 + import * as Layout from '#/components/Layout' 25 26 import {Loader} from '#/components/Loader' 26 27 27 28 type Props = NativeStackScreenProps< ··· 64 65 ) 65 66 66 67 return ( 67 - <ConvoProvider key={convoId} convoId={convoId}> 68 - <Inner /> 69 - </ConvoProvider> 68 + <Layout.Screen testID="convoScreen" style={web([{minHeight: 0}, a.flex_1])}> 69 + <ConvoProvider key={convoId} convoId={convoId}> 70 + <Inner /> 71 + </ConvoProvider> 72 + </Layout.Screen> 70 73 ) 71 74 } 72 75 ··· 100 103 101 104 if (convoState.status === ConvoStatus.Error) { 102 105 return ( 103 - <CenteredView style={a.flex_1} sideBorders> 106 + <CenteredView style={[a.flex_1]} sideBorders> 104 107 <MessagesListHeader /> 105 108 <Error 106 109 title={_(msg`Something went wrong`)}
+89 -86
src/screens/Messages/Settings.tsx
··· 16 16 import {Admonition} from '#/components/Admonition' 17 17 import {Divider} from '#/components/Divider' 18 18 import * as Toggle from '#/components/forms/Toggle' 19 + import * as Layout from '#/components/Layout' 19 20 import {Text} from '#/components/Typography' 20 21 import {useBackgroundNotificationPreferences} from '../../../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider' 21 22 ··· 55 56 ) 56 57 57 58 return ( 58 - <ScrollView stickyHeaderIndices={[0]}> 59 - <ViewHeader title={_(msg`Chat Settings`)} showOnDesktop showBorder /> 60 - <View style={[a.p_lg, a.gap_md]}> 61 - <Text style={[a.text_lg, a.font_bold]}> 62 - <Trans>Allow new messages from</Trans> 63 - </Text> 64 - <Toggle.Group 65 - label={_(msg`Allow new messages from`)} 66 - type="radio" 67 - values={[ 68 - (profile?.associated?.chat?.allowIncoming as AllowIncoming) ?? 69 - 'following', 70 - ]} 71 - onChange={onSelectMessagesFrom}> 72 - <View> 73 - <Toggle.Item 74 - name="all" 75 - label={_(msg`Everyone`)} 76 - style={[a.justify_between, a.py_sm]}> 77 - <Toggle.LabelText> 78 - <Trans>Everyone</Trans> 79 - </Toggle.LabelText> 80 - <Toggle.Radio /> 81 - </Toggle.Item> 82 - <Toggle.Item 83 - name="following" 84 - label={_(msg`Users I follow`)} 85 - style={[a.justify_between, a.py_sm]}> 86 - <Toggle.LabelText> 87 - <Trans>Users I follow</Trans> 88 - </Toggle.LabelText> 89 - <Toggle.Radio /> 90 - </Toggle.Item> 91 - <Toggle.Item 92 - name="none" 93 - label={_(msg`No one`)} 94 - style={[a.justify_between, a.py_sm]}> 95 - <Toggle.LabelText> 96 - <Trans>No one</Trans> 97 - </Toggle.LabelText> 98 - <Toggle.Radio /> 99 - </Toggle.Item> 100 - </View> 101 - </Toggle.Group> 102 - <Admonition type="tip"> 103 - <Trans> 104 - You can continue ongoing conversations regardless of which setting 105 - you choose. 106 - </Trans> 107 - </Admonition> 108 - {isNative && ( 109 - <> 110 - <Divider style={a.my_md} /> 111 - <Text style={[a.text_lg, a.font_bold]}> 112 - <Trans>Notification Sounds</Trans> 113 - </Text> 114 - <Toggle.Group 115 - label={_(msg`Notification sounds`)} 116 - type="radio" 117 - values={[preferences.playSoundChat ? 'enabled' : 'disabled']} 118 - onChange={onSelectSoundSetting}> 119 - <View> 120 - <Toggle.Item 121 - name="enabled" 122 - label={_(msg`Enabled`)} 123 - style={[a.justify_between, a.py_sm]}> 124 - <Toggle.LabelText> 125 - <Trans>Enabled</Trans> 126 - </Toggle.LabelText> 127 - <Toggle.Radio /> 128 - </Toggle.Item> 129 - <Toggle.Item 130 - name="disabled" 131 - label={_(msg`Disabled`)} 132 - style={[a.justify_between, a.py_sm]}> 133 - <Toggle.LabelText> 134 - <Trans>Disabled</Trans> 135 - </Toggle.LabelText> 136 - <Toggle.Radio /> 137 - </Toggle.Item> 138 - </View> 139 - </Toggle.Group> 140 - </> 141 - )} 142 - </View> 143 - </ScrollView> 59 + <Layout.Screen testID="messagesSettingsScreen"> 60 + <ScrollView stickyHeaderIndices={[0]}> 61 + <ViewHeader title={_(msg`Chat Settings`)} showOnDesktop showBorder /> 62 + <View style={[a.p_lg, a.gap_md]}> 63 + <Text style={[a.text_lg, a.font_bold]}> 64 + <Trans>Allow new messages from</Trans> 65 + </Text> 66 + <Toggle.Group 67 + label={_(msg`Allow new messages from`)} 68 + type="radio" 69 + values={[ 70 + (profile?.associated?.chat?.allowIncoming as AllowIncoming) ?? 71 + 'following', 72 + ]} 73 + onChange={onSelectMessagesFrom}> 74 + <View> 75 + <Toggle.Item 76 + name="all" 77 + label={_(msg`Everyone`)} 78 + style={[a.justify_between, a.py_sm]}> 79 + <Toggle.LabelText> 80 + <Trans>Everyone</Trans> 81 + </Toggle.LabelText> 82 + <Toggle.Radio /> 83 + </Toggle.Item> 84 + <Toggle.Item 85 + name="following" 86 + label={_(msg`Users I follow`)} 87 + style={[a.justify_between, a.py_sm]}> 88 + <Toggle.LabelText> 89 + <Trans>Users I follow</Trans> 90 + </Toggle.LabelText> 91 + <Toggle.Radio /> 92 + </Toggle.Item> 93 + <Toggle.Item 94 + name="none" 95 + label={_(msg`No one`)} 96 + style={[a.justify_between, a.py_sm]}> 97 + <Toggle.LabelText> 98 + <Trans>No one</Trans> 99 + </Toggle.LabelText> 100 + <Toggle.Radio /> 101 + </Toggle.Item> 102 + </View> 103 + </Toggle.Group> 104 + <Admonition type="tip"> 105 + <Trans> 106 + You can continue ongoing conversations regardless of which setting 107 + you choose. 108 + </Trans> 109 + </Admonition> 110 + {isNative && ( 111 + <> 112 + <Divider style={a.my_md} /> 113 + <Text style={[a.text_lg, a.font_bold]}> 114 + <Trans>Notification Sounds</Trans> 115 + </Text> 116 + <Toggle.Group 117 + label={_(msg`Notification sounds`)} 118 + type="radio" 119 + values={[preferences.playSoundChat ? 'enabled' : 'disabled']} 120 + onChange={onSelectSoundSetting}> 121 + <View> 122 + <Toggle.Item 123 + name="enabled" 124 + label={_(msg`Enabled`)} 125 + style={[a.justify_between, a.py_sm]}> 126 + <Toggle.LabelText> 127 + <Trans>Enabled</Trans> 128 + </Toggle.LabelText> 129 + <Toggle.Radio /> 130 + </Toggle.Item> 131 + <Toggle.Item 132 + name="disabled" 133 + label={_(msg`Disabled`)} 134 + style={[a.justify_between, a.py_sm]}> 135 + <Toggle.LabelText> 136 + <Trans>Disabled</Trans> 137 + </Toggle.LabelText> 138 + <Toggle.Radio /> 139 + </Toggle.Item> 140 + </View> 141 + </Toggle.Group> 142 + </> 143 + )} 144 + </View> 145 + </ScrollView> 146 + </Layout.Screen> 144 147 ) 145 148 }
+27 -24
src/screens/Moderation/index.tsx
··· 41 41 import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group' 42 42 import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person' 43 43 import * as LabelingService from '#/components/LabelingServiceCard' 44 + import * as Layout from '#/components/Layout' 44 45 import {InlineLinkText, Link} from '#/components/Link' 45 46 import {Loader} from '#/components/Loader' 46 47 import {GlobalLabelPreference} from '#/components/moderation/LabelPreference' ··· 94 95 const error = preferencesError 95 96 96 97 return ( 97 - <CenteredView 98 - testID="moderationScreen" 99 - style={[ 100 - t.atoms.border_contrast_low, 101 - t.atoms.bg, 102 - {minHeight: height}, 103 - ...(gtMobile ? [a.border_l, a.border_r] : []), 104 - ]}> 105 - <ViewHeader title={_(msg`Moderation`)} showOnDesktop /> 98 + <Layout.Screen testID="moderationScreen"> 99 + <CenteredView 100 + testID="moderationScreen" 101 + style={[ 102 + t.atoms.border_contrast_low, 103 + t.atoms.bg, 104 + {minHeight: height}, 105 + ...(gtMobile ? [a.border_l, a.border_r] : []), 106 + ]}> 107 + <ViewHeader title={_(msg`Moderation`)} showOnDesktop /> 106 108 107 - {isLoading ? ( 108 - <View style={[a.w_full, a.align_center, a.pt_2xl]}> 109 - <Loader size="xl" fill={t.atoms.text.color} /> 110 - </View> 111 - ) : error || !preferences ? ( 112 - <ErrorState 113 - error={ 114 - preferencesError?.toString() || 115 - _(msg`Something went wrong, please try again.`) 116 - } 117 - /> 118 - ) : ( 119 - <ModerationScreenInner preferences={preferences} /> 120 - )} 121 - </CenteredView> 109 + {isLoading ? ( 110 + <View style={[a.w_full, a.align_center, a.pt_2xl]}> 111 + <Loader size="xl" fill={t.atoms.text.color} /> 112 + </View> 113 + ) : error || !preferences ? ( 114 + <ErrorState 115 + error={ 116 + preferencesError?.toString() || 117 + _(msg`Something went wrong, please try again.`) 118 + } 119 + /> 120 + ) : ( 121 + <ModerationScreenInner preferences={preferences} /> 122 + )} 123 + </CenteredView> 124 + </Layout.Screen> 122 125 ) 123 126 } 124 127
+10 -8
src/screens/Post/PostLikedBy.tsx
··· 5 5 6 6 import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 7 7 import {makeRecordUri} from '#/lib/strings/url-helpers' 8 + import {isWeb} from '#/platform/detection' 8 9 import {useSetMinimalShellMode} from '#/state/shell' 9 - import {isWeb} from 'platform/detection' 10 10 import {PostLikedBy as PostLikedByComponent} from '#/view/com/post-thread/PostLikedBy' 11 11 import {ViewHeader} from '#/view/com/util/ViewHeader' 12 - import {CenteredView} from 'view/com/util/Views' 13 - import {atoms as a} from '#/alf' 12 + import {CenteredView} from '#/view/com/util/Views' 13 + import * as Layout from '#/components/Layout' 14 14 import {ListHeaderDesktop} from '#/components/Lists' 15 15 16 16 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'> ··· 27 27 ) 28 28 29 29 return ( 30 - <CenteredView style={a.util_screen_outer} sideBorders={true}> 31 - <ListHeaderDesktop title={_(msg`Liked By`)} /> 32 - <ViewHeader title={_(msg`Liked By`)} showBorder={!isWeb} /> 33 - <PostLikedByComponent uri={uri} /> 34 - </CenteredView> 30 + <Layout.Screen> 31 + <CenteredView sideBorders={true}> 32 + <ListHeaderDesktop title={_(msg`Liked By`)} /> 33 + <ViewHeader title={_(msg`Liked By`)} showBorder={!isWeb} /> 34 + <PostLikedByComponent uri={uri} /> 35 + </CenteredView> 36 + </Layout.Screen> 35 37 ) 36 38 }
+10 -8
src/screens/Post/PostQuotes.tsx
··· 5 5 6 6 import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 7 7 import {makeRecordUri} from '#/lib/strings/url-helpers' 8 + import {isWeb} from '#/platform/detection' 8 9 import {useSetMinimalShellMode} from '#/state/shell' 9 - import {isWeb} from 'platform/detection' 10 10 import {PostQuotes as PostQuotesComponent} from '#/view/com/post-thread/PostQuotes' 11 11 import {ViewHeader} from '#/view/com/util/ViewHeader' 12 - import {CenteredView} from 'view/com/util/Views' 13 - import {atoms as a} from '#/alf' 12 + import {CenteredView} from '#/view/com/util/Views' 13 + import * as Layout from '#/components/Layout' 14 14 import {ListHeaderDesktop} from '#/components/Lists' 15 15 16 16 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostQuotes'> ··· 27 27 ) 28 28 29 29 return ( 30 - <CenteredView style={a.util_screen_outer} sideBorders={true}> 31 - <ListHeaderDesktop title={_(msg`Quotes`)} /> 32 - <ViewHeader title={_(msg`Quotes`)} showBorder={!isWeb} /> 33 - <PostQuotesComponent uri={uri} /> 34 - </CenteredView> 30 + <Layout.Screen> 31 + <CenteredView sideBorders={true}> 32 + <ListHeaderDesktop title={_(msg`Quotes`)} /> 33 + <ViewHeader title={_(msg`Quotes`)} showBorder={!isWeb} /> 34 + <PostQuotesComponent uri={uri} /> 35 + </CenteredView> 36 + </Layout.Screen> 35 37 ) 36 38 }
+10 -8
src/screens/Post/PostRepostedBy.tsx
··· 5 5 6 6 import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 7 7 import {makeRecordUri} from '#/lib/strings/url-helpers' 8 + import {isWeb} from '#/platform/detection' 8 9 import {useSetMinimalShellMode} from '#/state/shell' 9 - import {isWeb} from 'platform/detection' 10 10 import {PostRepostedBy as PostRepostedByComponent} from '#/view/com/post-thread/PostRepostedBy' 11 11 import {ViewHeader} from '#/view/com/util/ViewHeader' 12 - import {CenteredView} from 'view/com/util/Views' 13 - import {atoms as a} from '#/alf' 12 + import {CenteredView} from '#/view/com/util/Views' 13 + import * as Layout from '#/components/Layout' 14 14 import {ListHeaderDesktop} from '#/components/Lists' 15 15 16 16 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'> ··· 27 27 ) 28 28 29 29 return ( 30 - <CenteredView style={a.util_screen_outer} sideBorders={true}> 31 - <ListHeaderDesktop title={_(msg`Reposted By`)} /> 32 - <ViewHeader title={_(msg`Reposted By`)} showBorder={!isWeb} /> 33 - <PostRepostedByComponent uri={uri} /> 34 - </CenteredView> 30 + <Layout.Screen> 31 + <CenteredView sideBorders={true}> 32 + <ListHeaderDesktop title={_(msg`Reposted By`)} /> 33 + <ViewHeader title={_(msg`Reposted By`)} showBorder={!isWeb} /> 34 + <PostRepostedByComponent uri={uri} /> 35 + </CenteredView> 36 + </Layout.Screen> 35 37 ) 36 38 }
+15 -13
src/screens/Profile/KnownFollowers.tsx
··· 1 1 import React from 'react' 2 - import {View} from 'react-native' 3 2 import {AppBskyActorDefs} from '@atproto/api' 4 3 import {msg} from '@lingui/macro' 5 4 import {useLingui} from '@lingui/react' 6 5 import {useFocusEffect} from '@react-navigation/native' 7 6 7 + import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' 8 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 8 9 import {cleanError} from '#/lib/strings/errors' 9 10 import {logger} from '#/logger' 10 11 import {useProfileKnownFollowersQuery} from '#/state/queries/known-followers' 11 12 import {useResolveDidQuery} from '#/state/queries/resolve-uri' 12 13 import {useSetMinimalShellMode} from '#/state/shell' 13 - import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' 14 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 15 14 import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' 16 15 import {List} from '#/view/com/util/List' 17 16 import {ViewHeader} from '#/view/com/util/ViewHeader' 17 + import * as Layout from '#/components/Layout' 18 18 import { 19 19 ListFooter, 20 20 ListHeaderDesktop, ··· 92 92 93 93 if (followers.length < 1) { 94 94 return ( 95 - <ListMaybePlaceholder 96 - isLoading={isDidLoading || isFollowersLoading} 97 - isError={isError} 98 - emptyType="results" 99 - emptyMessage={_(msg`You don't follow any users who follow @${name}.`)} 100 - errorMessage={cleanError(resolveError || error)} 101 - onRetry={isError ? refetch : undefined} 102 - /> 95 + <Layout.Screen> 96 + <ListMaybePlaceholder 97 + isLoading={isDidLoading || isFollowersLoading} 98 + isError={isError} 99 + emptyType="results" 100 + emptyMessage={_(msg`You don't follow any users who follow @${name}.`)} 101 + errorMessage={cleanError(resolveError || error)} 102 + onRetry={isError ? refetch : undefined} 103 + /> 104 + </Layout.Screen> 103 105 ) 104 106 } 105 107 106 108 return ( 107 - <View style={{flex: 1}}> 109 + <Layout.Screen> 108 110 <ViewHeader title={_(msg`Followers you know`)} /> 109 111 <List 110 112 data={followers} ··· 129 131 initialNumToRender={initialNumToRender} 130 132 windowSize={11} 131 133 /> 132 - </View> 134 + </Layout.Screen> 133 135 ) 134 136 }
+3 -3
src/screens/Profile/ProfileLabelerLikedBy.tsx
··· 1 1 import React from 'react' 2 - import {View} from 'react-native' 3 2 import {msg} from '@lingui/macro' 4 3 import {useLingui} from '@lingui/react' 5 4 import {useFocusEffect} from '@react-navigation/native' ··· 8 7 import {makeRecordUri} from '#/lib/strings/url-helpers' 9 8 import {useSetMinimalShellMode} from '#/state/shell' 10 9 import {ViewHeader} from '#/view/com/util/ViewHeader' 10 + import * as Layout from '#/components/Layout' 11 11 import {LikedByList} from '#/components/LikedByList' 12 12 13 13 export function ProfileLabelerLikedByScreen({ ··· 25 25 ) 26 26 27 27 return ( 28 - <View style={{flex: 1}}> 28 + <Layout.Screen> 29 29 <ViewHeader title={_(msg`Liked By`)} /> 30 30 <LikedByList uri={uri} /> 31 - </View> 31 + </Layout.Screen> 32 32 ) 33 33 }
+3 -3
src/screens/Settings/AppearanceSettings.tsx
··· 10 10 11 11 import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 12 12 import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 13 - import {s} from '#/lib/styles' 14 13 import {useSetThemePrefs, useThemePrefs} from '#/state/shell' 15 14 import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' 16 15 import {ScrollView} from '#/view/com/util/Views' ··· 21 20 import {Phone_Stroke2_Corner0_Rounded as PhoneIcon} from '#/components/icons/Phone' 22 21 import {TextSize_Stroke2_Corner0_Rounded as TextSize} from '#/components/icons/TextSize' 23 22 import {TitleCase_Stroke2_Corner0_Rounded as Aa} from '#/components/icons/TitleCase' 23 + import * as Layout from '#/components/Layout' 24 24 import {Text} from '#/components/Typography' 25 25 26 26 type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppearanceSettings'> ··· 76 76 77 77 return ( 78 78 <LayoutAnimationConfig skipExiting skipEntering> 79 - <View testID="preferencesThreadsScreen" style={s.hContentRegion}> 79 + <Layout.Screen testID="preferencesThreadsScreen"> 80 80 <ScrollView 81 81 // @ts-ignore web only -prf 82 82 dataSet={{'stable-gutters': 1}} ··· 180 180 </View> 181 181 </View> 182 182 </ScrollView> 183 - </View> 183 + </Layout.Screen> 184 184 </LayoutAnimationConfig> 185 185 ) 186 186 }
+19 -8
src/screens/StarterPack/StarterPackScreen.tsx
··· 53 53 import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid' 54 54 import {Pencil_Stroke2_Corner0_Rounded as Pencil} from '#/components/icons/Pencil' 55 55 import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash' 56 + import * as Layout from '#/components/Layout' 56 57 import {ListMaybePlaceholder} from '#/components/Lists' 57 58 import {Loader} from '#/components/Loader' 58 59 import * as Menu from '#/components/Menu' ··· 76 77 > 77 78 78 79 export function StarterPackScreen({route}: StarterPackScreeProps) { 79 - return <StarterPackScreenInner routeParams={route.params} /> 80 + return ( 81 + <Layout.Screen> 82 + <StarterPackScreenInner routeParams={route.params} /> 83 + </Layout.Screen> 84 + ) 80 85 } 81 86 82 87 export function StarterPackScreenShort({route}: StarterPackScreenShortProps) { ··· 91 96 92 97 if (isLoading || isError || !resolvedStarterPack) { 93 98 return ( 94 - <ListMaybePlaceholder 95 - isLoading={isLoading} 96 - isError={isError} 97 - errorMessage={_(msg`That starter pack could not be found.`)} 98 - emptyMessage={_(msg`That starter pack could not be found.`)} 99 - /> 99 + <Layout.Screen> 100 + <ListMaybePlaceholder 101 + isLoading={isLoading} 102 + isError={isError} 103 + errorMessage={_(msg`That starter pack could not be found.`)} 104 + emptyMessage={_(msg`That starter pack could not be found.`)} 105 + /> 106 + </Layout.Screen> 100 107 ) 101 108 } 102 - return <StarterPackScreenInner routeParams={resolvedStarterPack} /> 109 + return ( 110 + <Layout.Screen> 111 + <StarterPackScreenInner routeParams={resolvedStarterPack} /> 112 + </Layout.Screen> 113 + ) 103 114 } 104 115 105 116 export function StarterPackScreenInner({
+45 -38
src/screens/StarterPack/Wizard/index.tsx
··· 19 19 import {useFocusEffect, useNavigation} from '@react-navigation/native' 20 20 import {NativeStackScreenProps} from '@react-navigation/native-stack' 21 21 22 - import {logger} from '#/logger' 23 - import {HITSLOP_10, STARTER_PACK_MAX_SIZE} from 'lib/constants' 24 - import {createSanitizedDisplayName} from 'lib/moderation/create-sanitized-display-name' 25 - import {CommonNavigatorParams, NavigationProp} from 'lib/routes/types' 26 - import {logEvent} from 'lib/statsig/statsig' 27 - import {sanitizeDisplayName} from 'lib/strings/display-names' 28 - import {sanitizeHandle} from 'lib/strings/handles' 29 - import {enforceLen} from 'lib/strings/helpers' 22 + import {HITSLOP_10, STARTER_PACK_MAX_SIZE} from '#/lib/constants' 23 + import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' 24 + import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types' 25 + import {logEvent} from '#/lib/statsig/statsig' 26 + import {sanitizeDisplayName} from '#/lib/strings/display-names' 27 + import {sanitizeHandle} from '#/lib/strings/handles' 28 + import {enforceLen} from '#/lib/strings/helpers' 30 29 import { 31 30 getStarterPackOgCard, 32 31 parseStarterPackUri, 33 - } from 'lib/strings/starter-pack' 34 - import {isAndroid, isNative, isWeb} from 'platform/detection' 35 - import {useModerationOpts} from 'state/preferences/moderation-opts' 36 - import {useAllListMembersQuery} from 'state/queries/list-members' 37 - import {useProfileQuery} from 'state/queries/profile' 32 + } from '#/lib/strings/starter-pack' 33 + import {logger} from '#/logger' 34 + import {isAndroid, isNative, isWeb} from '#/platform/detection' 35 + import {useModerationOpts} from '#/state/preferences/moderation-opts' 36 + import {useAllListMembersQuery} from '#/state/queries/list-members' 37 + import {useProfileQuery} from '#/state/queries/profile' 38 38 import { 39 39 useCreateStarterPackMutation, 40 40 useEditStarterPackMutation, 41 41 useStarterPackQuery, 42 - } from 'state/queries/starter-packs' 43 - import {useSession} from 'state/session' 44 - import {useSetMinimalShellMode} from 'state/shell' 42 + } from '#/state/queries/starter-packs' 43 + import {useSession} from '#/state/session' 44 + import {useSetMinimalShellMode} from '#/state/shell' 45 45 import * as Toast from '#/view/com/util/Toast' 46 - import {UserAvatar} from 'view/com/util/UserAvatar' 47 - import {CenteredView} from 'view/com/util/Views' 46 + import {UserAvatar} from '#/view/com/util/UserAvatar' 47 + import {CenteredView} from '#/view/com/util/Views' 48 48 import {useWizardState, WizardStep} from '#/screens/StarterPack/Wizard/State' 49 49 import {StepDetails} from '#/screens/StarterPack/Wizard/StepDetails' 50 50 import {StepFeeds} from '#/screens/StarterPack/Wizard/StepFeeds' ··· 52 52 import {atoms as a, useTheme} from '#/alf' 53 53 import {Button, ButtonText} from '#/components/Button' 54 54 import {useDialogControl} from '#/components/Dialog' 55 + import * as Layout from '#/components/Layout' 55 56 import {ListMaybePlaceholder} from '#/components/Lists' 56 57 import {Loader} from '#/components/Loader' 57 58 import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog' ··· 97 98 98 99 if (!isReady) { 99 100 return ( 100 - <ListMaybePlaceholder 101 - isLoading={ 102 - isLoadingStarterPack || isLoadingProfiles || isLoadingProfile 103 - } 104 - isError={isErrorStarterPack || isErrorProfiles || isErrorProfile} 105 - errorMessage={_(msg`That starter pack could not be found.`)} 106 - /> 101 + <Layout.Screen> 102 + <ListMaybePlaceholder 103 + isLoading={ 104 + isLoadingStarterPack || isLoadingProfiles || isLoadingProfile 105 + } 106 + isError={isErrorStarterPack || isErrorProfiles || isErrorProfile} 107 + errorMessage={_(msg`That starter pack could not be found.`)} 108 + /> 109 + </Layout.Screen> 107 110 ) 108 111 } else if (isEdit && starterPack?.creator.did !== currentAccount?.did) { 109 112 return ( 110 - <ListMaybePlaceholder 111 - isLoading={false} 112 - isError={true} 113 - errorMessage={_(msg`That starter pack could not be found.`)} 114 - /> 113 + <Layout.Screen> 114 + <ListMaybePlaceholder 115 + isLoading={false} 116 + isError={true} 117 + errorMessage={_(msg`That starter pack could not be found.`)} 118 + /> 119 + </Layout.Screen> 115 120 ) 116 121 } 117 122 118 123 return ( 119 - <Provider starterPack={starterPack} listItems={listItems}> 120 - <WizardInner 121 - currentStarterPack={starterPack} 122 - currentListItems={listItems} 123 - profile={profile} 124 - moderationOpts={moderationOpts} 125 - /> 126 - </Provider> 124 + <Layout.Screen> 125 + <Provider starterPack={starterPack} listItems={listItems}> 126 + <WizardInner 127 + currentStarterPack={starterPack} 128 + currentListItems={listItems} 129 + profile={profile} 130 + moderationOpts={moderationOpts} 131 + /> 132 + </Provider> 133 + </Layout.Screen> 127 134 ) 128 135 } 129 136
+3 -2
src/view/screens/AccessibilitySettings.tsx
··· 27 27 import {Text} from '#/view/com/util/text/Text' 28 28 import {ScrollView} from '#/view/com/util/Views' 29 29 import {atoms as a} from '#/alf' 30 + import * as Layout from '#/components/Layout' 30 31 31 32 type Props = NativeStackScreenProps< 32 33 CommonNavigatorParams, ··· 54 55 ) 55 56 56 57 return ( 57 - <View style={s.hContentRegion} testID="accessibilitySettingsScreen"> 58 + <Layout.Screen testID="accessibilitySettingsScreen"> 58 59 <SimpleViewHeader 59 60 showBackButton={isTabletOrMobile} 60 61 style={[ ··· 128 129 </> 129 130 )} 130 131 </ScrollView> 131 - </View> 132 + </Layout.Screen> 132 133 ) 133 134 } 134 135
+9
src/view/screens/AppPasswords.tsx
··· 30 30 import {CenteredView} from '#/view/com/util/Views' 31 31 import {atoms as a} from '#/alf' 32 32 import {useDialogControl} from '#/components/Dialog' 33 + import * as Layout from '#/components/Layout' 33 34 import * as Prompt from '#/components/Prompt' 34 35 35 36 type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppPasswords'> 36 37 export function AppPasswords({}: Props) { 38 + return ( 39 + <Layout.Screen testID="AppPasswordsScreen"> 40 + <AppPasswordsInner /> 41 + </Layout.Screen> 42 + ) 43 + } 44 + 45 + function AppPasswordsInner() { 37 46 const pal = usePalette('default') 38 47 const {_} = useLingui() 39 48 const setMinimalShellMode = useSetMinimalShellMode()
+13 -11
src/view/screens/CommunityGuidelines.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 3 5 import {useFocusEffect} from '@react-navigation/native' 4 - import {Text} from 'view/com/util/text/Text' 5 - import {TextLink} from 'view/com/util/Link' 6 - import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' 7 - import {ViewHeader} from '../com/util/ViewHeader' 8 - import {ScrollView} from 'view/com/util/Views' 9 - import {usePalette} from 'lib/hooks/usePalette' 10 - import {s} from 'lib/styles' 6 + 7 + import {usePalette} from '#/lib/hooks/usePalette' 8 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 9 + import {s} from '#/lib/styles' 11 10 import {useSetMinimalShellMode} from '#/state/shell' 12 - import {Trans, msg} from '@lingui/macro' 13 - import {useLingui} from '@lingui/react' 11 + import {TextLink} from '#/view/com/util/Link' 12 + import {Text} from '#/view/com/util/text/Text' 13 + import {ScrollView} from '#/view/com/util/Views' 14 + import * as Layout from '#/components/Layout' 15 + import {ViewHeader} from '../com/util/ViewHeader' 14 16 15 17 type Props = NativeStackScreenProps< 16 18 CommonNavigatorParams, ··· 28 30 ) 29 31 30 32 return ( 31 - <View> 33 + <Layout.Screen> 32 34 <ViewHeader title={_(msg`Community Guidelines`)} /> 33 35 <ScrollView style={[s.hContentRegion, pal.view]}> 34 36 <View style={[s.p20]}> ··· 45 47 </View> 46 48 <View style={s.footerSpacer} /> 47 49 </ScrollView> 48 - </View> 50 + </Layout.Screen> 49 51 ) 50 52 }
+13 -11
src/view/screens/CopyrightPolicy.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 3 5 import {useFocusEffect} from '@react-navigation/native' 4 - import {Text} from 'view/com/util/text/Text' 5 - import {TextLink} from 'view/com/util/Link' 6 - import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' 7 - import {ViewHeader} from '../com/util/ViewHeader' 8 - import {ScrollView} from 'view/com/util/Views' 9 - import {usePalette} from 'lib/hooks/usePalette' 10 - import {s} from 'lib/styles' 6 + 7 + import {usePalette} from '#/lib/hooks/usePalette' 8 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 9 + import {s} from '#/lib/styles' 11 10 import {useSetMinimalShellMode} from '#/state/shell' 12 - import {Trans, msg} from '@lingui/macro' 13 - import {useLingui} from '@lingui/react' 11 + import {TextLink} from '#/view/com/util/Link' 12 + import {Text} from '#/view/com/util/text/Text' 13 + import {ScrollView} from '#/view/com/util/Views' 14 + import * as Layout from '#/components/Layout' 15 + import {ViewHeader} from '../com/util/ViewHeader' 14 16 15 17 type Props = NativeStackScreenProps<CommonNavigatorParams, 'CopyrightPolicy'> 16 18 export const CopyrightPolicyScreen = (_props: Props) => { ··· 25 27 ) 26 28 27 29 return ( 28 - <View> 30 + <Layout.Screen> 29 31 <ViewHeader title={_(msg`Copyright Policy`)} /> 30 32 <ScrollView style={[s.hContentRegion, pal.view]}> 31 33 <View style={[s.p20]}> ··· 42 44 </View> 43 45 <View style={s.footerSpacer} /> 44 46 </ScrollView> 45 - </View> 47 + </Layout.Screen> 46 48 ) 47 49 }
+27 -20
src/view/screens/Debug.tsx
··· 1 1 import React from 'react' 2 2 import {ScrollView, View} from 'react-native' 3 - import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' 4 - import {ViewHeader} from '../com/util/ViewHeader' 5 - import {ThemeProvider, PaletteColorName} from 'lib/ThemeContext' 6 - import {usePalette} from 'lib/hooks/usePalette' 7 - import {s} from 'lib/styles' 8 - import * as Toast from 'view/com/util/Toast' 9 - import {Text} from '../com/util/text/Text' 10 - import {ViewSelector} from '../com/util/ViewSelector' 11 - import {EmptyState} from '../com/util/EmptyState' 12 - import * as LoadingPlaceholder from '../com/util/LoadingPlaceholder' 13 - import {Button, ButtonType} from '../com/util/forms/Button' 14 - import {DropdownButton, DropdownItem} from '../com/util/forms/DropdownButton' 15 - import {ToggleButton} from '../com/util/forms/ToggleButton' 16 - import {RadioGroup} from '../com/util/forms/RadioGroup' 17 - import {ErrorScreen} from '../com/util/error/ErrorScreen' 18 - import {ErrorMessage} from '../com/util/error/ErrorMessage' 19 3 import {msg} from '@lingui/macro' 20 4 import {useLingui} from '@lingui/react' 21 5 6 + import {usePalette} from '#/lib/hooks/usePalette' 7 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 8 + import {s} from '#/lib/styles' 9 + import {PaletteColorName, ThemeProvider} from '#/lib/ThemeContext' 10 + import {EmptyState} from '#/view/com/util/EmptyState' 11 + import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' 12 + import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' 13 + import {Button, ButtonType} from '#/view/com/util/forms/Button' 14 + import { 15 + DropdownButton, 16 + DropdownItem, 17 + } from '#/view/com/util/forms/DropdownButton' 18 + import {RadioGroup} from '#/view/com/util/forms/RadioGroup' 19 + import {ToggleButton} from '#/view/com/util/forms/ToggleButton' 20 + import * as LoadingPlaceholder from '#/view/com/util/LoadingPlaceholder' 21 + import {Text} from '#/view/com/util/text/Text' 22 + import * as Toast from '#/view/com/util/Toast' 23 + import {ViewHeader} from '#/view/com/util/ViewHeader' 24 + import {ViewSelector} from '#/view/com/util/ViewSelector' 25 + import * as Layout from '#/components/Layout' 26 + 22 27 const MAIN_VIEWS = ['Base', 'Controls', 'Error', 'Notifs'] 23 28 24 29 export const DebugScreen = ({}: NativeStackScreenProps< ··· 33 38 } 34 39 return ( 35 40 <ThemeProvider theme={colorScheme}> 36 - <DebugInner 37 - colorScheme={colorScheme} 38 - onToggleColorScheme={onToggleColorScheme} 39 - /> 41 + <Layout.Screen> 42 + <DebugInner 43 + colorScheme={colorScheme} 44 + onToggleColorScheme={onToggleColorScheme} 45 + /> 46 + </Layout.Screen> 40 47 </ThemeProvider> 41 48 ) 42 49 }
+289 -272
src/view/screens/DebugMod.tsx
··· 21 21 import {useLingui} from '@lingui/react' 22 22 23 23 import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings' 24 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 24 25 import {moderationOptsOverrideContext} from '#/state/preferences/moderation-opts' 25 26 import {FeedNotification} from '#/state/queries/notifications/types' 26 27 import { ··· 28 29 shouldFilterNotif, 29 30 } from '#/state/queries/notifications/util' 30 31 import {useSession} from '#/state/session' 31 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 32 32 import {CenteredView, ScrollView} from '#/view/com/util/Views' 33 33 import {ProfileHeaderStandard} from '#/screens/Profile/Header/ProfileHeaderStandard' 34 34 import {atoms as a, useTheme} from '#/alf' ··· 41 41 ChevronBottom_Stroke2_Corner0_Rounded as ChevronBottom, 42 42 ChevronTop_Stroke2_Corner0_Rounded as ChevronTop, 43 43 } from '#/components/icons/Chevron' 44 + import * as Layout from '#/components/Layout' 44 45 import {H1, H3, P, Text} from '#/components/Typography' 45 46 import {ScreenHider} from '../../components/moderation/ScreenHider' 46 47 import {FeedItem as NotifFeedItem} from '../com/notifications/FeedItem' ··· 264 265 }, [post, modOpts]) 265 266 266 267 return ( 267 - <moderationOptsOverrideContext.Provider value={modOpts}> 268 - <ScrollView> 269 - <CenteredView style={[t.atoms.bg, a.px_lg, a.py_lg]}> 270 - <H1 style={[a.text_5xl, a.font_bold, a.pb_lg]}>Moderation states</H1> 268 + <Layout.Screen> 269 + <moderationOptsOverrideContext.Provider value={modOpts}> 270 + <ScrollView> 271 + <CenteredView style={[t.atoms.bg, a.px_lg, a.py_lg]}> 272 + <H1 style={[a.text_5xl, a.font_bold, a.pb_lg]}> 273 + Moderation states 274 + </H1> 271 275 272 - <Heading title="" subtitle="Scenario" /> 273 - <ToggleButton.Group 274 - label="Scenario" 275 - values={scenario} 276 - onChange={setScenario}> 277 - <ToggleButton.Button name="label" label="Label"> 278 - <ToggleButton.ButtonText>Label</ToggleButton.ButtonText> 279 - </ToggleButton.Button> 280 - <ToggleButton.Button name="block" label="Block"> 281 - <ToggleButton.ButtonText>Block</ToggleButton.ButtonText> 282 - </ToggleButton.Button> 283 - <ToggleButton.Button name="mute" label="Mute"> 284 - <ToggleButton.ButtonText>Mute</ToggleButton.ButtonText> 285 - </ToggleButton.Button> 286 - </ToggleButton.Group> 276 + <Heading title="" subtitle="Scenario" /> 277 + <ToggleButton.Group 278 + label="Scenario" 279 + values={scenario} 280 + onChange={setScenario}> 281 + <ToggleButton.Button name="label" label="Label"> 282 + <ToggleButton.ButtonText>Label</ToggleButton.ButtonText> 283 + </ToggleButton.Button> 284 + <ToggleButton.Button name="block" label="Block"> 285 + <ToggleButton.ButtonText>Block</ToggleButton.ButtonText> 286 + </ToggleButton.Button> 287 + <ToggleButton.Button name="mute" label="Mute"> 288 + <ToggleButton.ButtonText>Mute</ToggleButton.ButtonText> 289 + </ToggleButton.Button> 290 + </ToggleButton.Group> 287 291 288 - {scenario[0] === 'label' && ( 289 - <> 290 - <View 291 - style={[ 292 - a.border, 293 - a.rounded_sm, 294 - a.mt_lg, 295 - a.mb_lg, 296 - a.p_lg, 297 - t.atoms.border_contrast_medium, 298 - ]}> 299 - <Toggle.Group 300 - label="Toggle" 301 - type="radio" 302 - values={label} 303 - onChange={setLabel}> 304 - <View style={[a.flex_row, a.gap_md, a.flex_wrap]}> 305 - {LABEL_VALUES.map(labelValue => { 306 - let targetFixed = target[0] 307 - if ( 308 - targetFixed !== 'account' && 309 - targetFixed !== 'profile' 310 - ) { 311 - targetFixed = 'content' 312 - } 313 - const disabled = 314 - isSelfLabel && 315 - LABELS[labelValue].flags.includes('no-self') 316 - return ( 317 - <Toggle.Item 318 - key={labelValue} 319 - name={labelValue} 320 - label={labelStrings[labelValue].name} 321 - disabled={disabled} 322 - style={disabled ? {opacity: 0.5} : undefined}> 323 - <Toggle.Radio /> 324 - <Toggle.LabelText>{labelValue}</Toggle.LabelText> 325 - </Toggle.Item> 326 - ) 327 - })} 328 - <Toggle.Item 329 - name="custom" 330 - label="Custom label" 331 - disabled={isSelfLabel} 332 - style={isSelfLabel ? {opacity: 0.5} : undefined}> 333 - <Toggle.Radio /> 334 - <Toggle.LabelText>Custom label</Toggle.LabelText> 335 - </Toggle.Item> 336 - </View> 337 - </Toggle.Group> 338 - 339 - {label[0] === 'custom' ? ( 340 - <CustomLabelForm 341 - def={customLabelDef} 342 - setDef={setCustomLabelDef} 343 - /> 344 - ) : ( 345 - <> 346 - <View style={{height: 10}} /> 347 - <Divider /> 348 - </> 349 - )} 350 - 351 - <View style={{height: 10}} /> 352 - 353 - <SmallToggler label="Advanced"> 292 + {scenario[0] === 'label' && ( 293 + <> 294 + <View 295 + style={[ 296 + a.border, 297 + a.rounded_sm, 298 + a.mt_lg, 299 + a.mb_lg, 300 + a.p_lg, 301 + t.atoms.border_contrast_medium, 302 + ]}> 354 303 <Toggle.Group 355 304 label="Toggle" 356 - type="checkbox" 357 - values={scenarioSwitches} 358 - onChange={setScenarioSwitches}> 359 - <View style={[a.gap_md, a.flex_row, a.flex_wrap, a.pt_md]}> 360 - <Toggle.Item name="targetMe" label="Target is me"> 361 - <Toggle.Checkbox /> 362 - <Toggle.LabelText>Target is me</Toggle.LabelText> 363 - </Toggle.Item> 364 - <Toggle.Item name="following" label="Following target"> 365 - <Toggle.Checkbox /> 366 - <Toggle.LabelText>Following target</Toggle.LabelText> 367 - </Toggle.Item> 368 - <Toggle.Item name="selfLabel" label="Self label"> 369 - <Toggle.Checkbox /> 370 - <Toggle.LabelText>Self label</Toggle.LabelText> 371 - </Toggle.Item> 372 - <Toggle.Item name="noAdult" label="Adult disabled"> 373 - <Toggle.Checkbox /> 374 - <Toggle.LabelText>Adult disabled</Toggle.LabelText> 375 - </Toggle.Item> 376 - <Toggle.Item name="loggedOut" label="Logged out"> 377 - <Toggle.Checkbox /> 378 - <Toggle.LabelText>Logged out</Toggle.LabelText> 305 + type="radio" 306 + values={label} 307 + onChange={setLabel}> 308 + <View style={[a.flex_row, a.gap_md, a.flex_wrap]}> 309 + {LABEL_VALUES.map(labelValue => { 310 + let targetFixed = target[0] 311 + if ( 312 + targetFixed !== 'account' && 313 + targetFixed !== 'profile' 314 + ) { 315 + targetFixed = 'content' 316 + } 317 + const disabled = 318 + isSelfLabel && 319 + LABELS[labelValue].flags.includes('no-self') 320 + return ( 321 + <Toggle.Item 322 + key={labelValue} 323 + name={labelValue} 324 + label={labelStrings[labelValue].name} 325 + disabled={disabled} 326 + style={disabled ? {opacity: 0.5} : undefined}> 327 + <Toggle.Radio /> 328 + <Toggle.LabelText>{labelValue}</Toggle.LabelText> 329 + </Toggle.Item> 330 + ) 331 + })} 332 + <Toggle.Item 333 + name="custom" 334 + label="Custom label" 335 + disabled={isSelfLabel} 336 + style={isSelfLabel ? {opacity: 0.5} : undefined}> 337 + <Toggle.Radio /> 338 + <Toggle.LabelText>Custom label</Toggle.LabelText> 379 339 </Toggle.Item> 380 340 </View> 381 341 </Toggle.Group> 382 342 383 - {LABELS[label[0] as keyof typeof LABELS]?.configurable !== 384 - false && ( 385 - <View style={[a.mt_md]}> 386 - <Text 387 - style={[a.font_bold, a.text_xs, t.atoms.text, a.pb_sm]}> 388 - Preference 389 - </Text> 343 + {label[0] === 'custom' ? ( 344 + <CustomLabelForm 345 + def={customLabelDef} 346 + setDef={setCustomLabelDef} 347 + /> 348 + ) : ( 349 + <> 350 + <View style={{height: 10}} /> 351 + <Divider /> 352 + </> 353 + )} 354 + 355 + <View style={{height: 10}} /> 356 + 357 + <SmallToggler label="Advanced"> 358 + <Toggle.Group 359 + label="Toggle" 360 + type="checkbox" 361 + values={scenarioSwitches} 362 + onChange={setScenarioSwitches}> 363 + <View 364 + style={[a.gap_md, a.flex_row, a.flex_wrap, a.pt_md]}> 365 + <Toggle.Item name="targetMe" label="Target is me"> 366 + <Toggle.Checkbox /> 367 + <Toggle.LabelText>Target is me</Toggle.LabelText> 368 + </Toggle.Item> 369 + <Toggle.Item name="following" label="Following target"> 370 + <Toggle.Checkbox /> 371 + <Toggle.LabelText>Following target</Toggle.LabelText> 372 + </Toggle.Item> 373 + <Toggle.Item name="selfLabel" label="Self label"> 374 + <Toggle.Checkbox /> 375 + <Toggle.LabelText>Self label</Toggle.LabelText> 376 + </Toggle.Item> 377 + <Toggle.Item name="noAdult" label="Adult disabled"> 378 + <Toggle.Checkbox /> 379 + <Toggle.LabelText>Adult disabled</Toggle.LabelText> 380 + </Toggle.Item> 381 + <Toggle.Item name="loggedOut" label="Logged out"> 382 + <Toggle.Checkbox /> 383 + <Toggle.LabelText>Logged out</Toggle.LabelText> 384 + </Toggle.Item> 385 + </View> 386 + </Toggle.Group> 387 + 388 + {LABELS[label[0] as keyof typeof LABELS]?.configurable !== 389 + false && ( 390 + <View style={[a.mt_md]}> 391 + <Text 392 + style={[ 393 + a.font_bold, 394 + a.text_xs, 395 + t.atoms.text, 396 + a.pb_sm, 397 + ]}> 398 + Preference 399 + </Text> 400 + <Toggle.Group 401 + label="Preference" 402 + type="radio" 403 + values={visibility} 404 + onChange={setVisiblity}> 405 + <View 406 + style={[ 407 + a.flex_row, 408 + a.gap_md, 409 + a.flex_wrap, 410 + a.align_center, 411 + ]}> 412 + <Toggle.Item name="hide" label="Hide"> 413 + <Toggle.Radio /> 414 + <Toggle.LabelText>Hide</Toggle.LabelText> 415 + </Toggle.Item> 416 + <Toggle.Item name="warn" label="Warn"> 417 + <Toggle.Radio /> 418 + <Toggle.LabelText>Warn</Toggle.LabelText> 419 + </Toggle.Item> 420 + <Toggle.Item name="ignore" label="Ignore"> 421 + <Toggle.Radio /> 422 + <Toggle.LabelText>Ignore</Toggle.LabelText> 423 + </Toggle.Item> 424 + </View> 425 + </Toggle.Group> 426 + </View> 427 + )} 428 + </SmallToggler> 429 + </View> 430 + 431 + <View style={[a.flex_row, a.flex_wrap, a.gap_md]}> 432 + <View> 433 + <Text 434 + style={[ 435 + a.font_bold, 436 + a.text_xs, 437 + t.atoms.text, 438 + a.pl_md, 439 + a.pb_xs, 440 + ]}> 441 + Target 442 + </Text> 443 + <View 444 + style={[ 445 + a.border, 446 + a.rounded_full, 447 + a.px_md, 448 + a.py_sm, 449 + t.atoms.border_contrast_medium, 450 + t.atoms.bg, 451 + ]}> 390 452 <Toggle.Group 391 - label="Preference" 453 + label="Target" 392 454 type="radio" 393 - values={visibility} 394 - onChange={setVisiblity}> 395 - <View 396 - style={[ 397 - a.flex_row, 398 - a.gap_md, 399 - a.flex_wrap, 400 - a.align_center, 401 - ]}> 402 - <Toggle.Item name="hide" label="Hide"> 455 + values={target} 456 + onChange={setTarget}> 457 + <View style={[a.flex_row, a.gap_md, a.flex_wrap]}> 458 + <Toggle.Item name="account" label="Account"> 403 459 <Toggle.Radio /> 404 - <Toggle.LabelText>Hide</Toggle.LabelText> 460 + <Toggle.LabelText>Account</Toggle.LabelText> 405 461 </Toggle.Item> 406 - <Toggle.Item name="warn" label="Warn"> 462 + <Toggle.Item name="profile" label="Profile"> 407 463 <Toggle.Radio /> 408 - <Toggle.LabelText>Warn</Toggle.LabelText> 464 + <Toggle.LabelText>Profile</Toggle.LabelText> 409 465 </Toggle.Item> 410 - <Toggle.Item name="ignore" label="Ignore"> 466 + <Toggle.Item name="post" label="Post"> 467 + <Toggle.Radio /> 468 + <Toggle.LabelText>Post</Toggle.LabelText> 469 + </Toggle.Item> 470 + <Toggle.Item name="embed" label="Embed"> 411 471 <Toggle.Radio /> 412 - <Toggle.LabelText>Ignore</Toggle.LabelText> 472 + <Toggle.LabelText>Embed</Toggle.LabelText> 413 473 </Toggle.Item> 414 474 </View> 415 475 </Toggle.Group> 416 476 </View> 417 - )} 418 - </SmallToggler> 419 - </View> 420 - 421 - <View style={[a.flex_row, a.flex_wrap, a.gap_md]}> 422 - <View> 423 - <Text 424 - style={[ 425 - a.font_bold, 426 - a.text_xs, 427 - t.atoms.text, 428 - a.pl_md, 429 - a.pb_xs, 430 - ]}> 431 - Target 432 - </Text> 433 - <View 434 - style={[ 435 - a.border, 436 - a.rounded_full, 437 - a.px_md, 438 - a.py_sm, 439 - t.atoms.border_contrast_medium, 440 - t.atoms.bg, 441 - ]}> 442 - <Toggle.Group 443 - label="Target" 444 - type="radio" 445 - values={target} 446 - onChange={setTarget}> 447 - <View style={[a.flex_row, a.gap_md, a.flex_wrap]}> 448 - <Toggle.Item name="account" label="Account"> 449 - <Toggle.Radio /> 450 - <Toggle.LabelText>Account</Toggle.LabelText> 451 - </Toggle.Item> 452 - <Toggle.Item name="profile" label="Profile"> 453 - <Toggle.Radio /> 454 - <Toggle.LabelText>Profile</Toggle.LabelText> 455 - </Toggle.Item> 456 - <Toggle.Item name="post" label="Post"> 457 - <Toggle.Radio /> 458 - <Toggle.LabelText>Post</Toggle.LabelText> 459 - </Toggle.Item> 460 - <Toggle.Item name="embed" label="Embed"> 461 - <Toggle.Radio /> 462 - <Toggle.LabelText>Embed</Toggle.LabelText> 463 - </Toggle.Item> 464 - </View> 465 - </Toggle.Group> 466 477 </View> 467 478 </View> 468 - </View> 469 - </> 470 - )} 479 + </> 480 + )} 471 481 472 - <Spacer /> 482 + <Spacer /> 473 483 474 - <Heading title="" subtitle="Results" /> 484 + <Heading title="" subtitle="Results" /> 475 485 476 - <ToggleButton.Group label="Results" values={view} onChange={setView}> 477 - <ToggleButton.Button name="post" label="Post"> 478 - <ToggleButton.ButtonText>Post</ToggleButton.ButtonText> 479 - </ToggleButton.Button> 480 - <ToggleButton.Button name="notifications" label="Notifications"> 481 - <ToggleButton.ButtonText>Notifications</ToggleButton.ButtonText> 482 - </ToggleButton.Button> 483 - <ToggleButton.Button name="account" label="Account"> 484 - <ToggleButton.ButtonText>Account</ToggleButton.ButtonText> 485 - </ToggleButton.Button> 486 - <ToggleButton.Button name="data" label="Data"> 487 - <ToggleButton.ButtonText>Data</ToggleButton.ButtonText> 488 - </ToggleButton.Button> 489 - </ToggleButton.Group> 486 + <ToggleButton.Group 487 + label="Results" 488 + values={view} 489 + onChange={setView}> 490 + <ToggleButton.Button name="post" label="Post"> 491 + <ToggleButton.ButtonText>Post</ToggleButton.ButtonText> 492 + </ToggleButton.Button> 493 + <ToggleButton.Button name="notifications" label="Notifications"> 494 + <ToggleButton.ButtonText>Notifications</ToggleButton.ButtonText> 495 + </ToggleButton.Button> 496 + <ToggleButton.Button name="account" label="Account"> 497 + <ToggleButton.ButtonText>Account</ToggleButton.ButtonText> 498 + </ToggleButton.Button> 499 + <ToggleButton.Button name="data" label="Data"> 500 + <ToggleButton.ButtonText>Data</ToggleButton.ButtonText> 501 + </ToggleButton.Button> 502 + </ToggleButton.Group> 490 503 491 - <View 492 - style={[ 493 - a.border, 494 - a.rounded_sm, 495 - a.mt_lg, 496 - a.p_md, 497 - t.atoms.border_contrast_medium, 498 - ]}> 499 - {view[0] === 'post' && ( 500 - <> 501 - <Heading title="Post" subtitle="in feed" /> 502 - <MockPostFeedItem post={post} moderation={postModeration} /> 504 + <View 505 + style={[ 506 + a.border, 507 + a.rounded_sm, 508 + a.mt_lg, 509 + a.p_md, 510 + t.atoms.border_contrast_medium, 511 + ]}> 512 + {view[0] === 'post' && ( 513 + <> 514 + <Heading title="Post" subtitle="in feed" /> 515 + <MockPostFeedItem post={post} moderation={postModeration} /> 503 516 504 - <Heading title="Post" subtitle="viewed directly" /> 505 - <MockPostThreadItem post={post} moderation={postModeration} /> 517 + <Heading title="Post" subtitle="viewed directly" /> 518 + <MockPostThreadItem post={post} moderation={postModeration} /> 506 519 507 - <Heading title="Post" subtitle="reply in thread" /> 508 - <MockPostThreadItem 509 - post={post} 510 - moderation={postModeration} 511 - reply 512 - /> 513 - </> 514 - )} 520 + <Heading title="Post" subtitle="reply in thread" /> 521 + <MockPostThreadItem 522 + post={post} 523 + moderation={postModeration} 524 + reply 525 + /> 526 + </> 527 + )} 515 528 516 - {view[0] === 'notifications' && ( 517 - <> 518 - <Heading title="Notification" subtitle="quote or reply" /> 519 - <MockNotifItem notif={replyNotif} moderationOpts={modOpts} /> 520 - <View style={{height: 20}} /> 521 - <Heading title="Notification" subtitle="follow or like" /> 522 - <MockNotifItem notif={followNotif} moderationOpts={modOpts} /> 523 - </> 524 - )} 529 + {view[0] === 'notifications' && ( 530 + <> 531 + <Heading title="Notification" subtitle="quote or reply" /> 532 + <MockNotifItem notif={replyNotif} moderationOpts={modOpts} /> 533 + <View style={{height: 20}} /> 534 + <Heading title="Notification" subtitle="follow or like" /> 535 + <MockNotifItem notif={followNotif} moderationOpts={modOpts} /> 536 + </> 537 + )} 525 538 526 - {view[0] === 'account' && ( 527 - <> 528 - <Heading title="Account" subtitle="in listing" /> 529 - <MockAccountCard 530 - profile={profile} 531 - moderation={profileModeration} 532 - /> 539 + {view[0] === 'account' && ( 540 + <> 541 + <Heading title="Account" subtitle="in listing" /> 542 + <MockAccountCard 543 + profile={profile} 544 + moderation={profileModeration} 545 + /> 533 546 534 - <Heading title="Account" subtitle="viewing directly" /> 535 - <MockAccountScreen 536 - profile={profile} 537 - moderation={profileModeration} 538 - moderationOpts={modOpts} 539 - /> 540 - </> 541 - )} 547 + <Heading title="Account" subtitle="viewing directly" /> 548 + <MockAccountScreen 549 + profile={profile} 550 + moderation={profileModeration} 551 + moderationOpts={modOpts} 552 + /> 553 + </> 554 + )} 542 555 543 - {view[0] === 'data' && ( 544 - <> 545 - <ModerationUIView 546 - label="Profile Moderation UI" 547 - mod={profileModeration} 548 - /> 549 - <ModerationUIView 550 - label="Post Moderation UI" 551 - mod={postModeration} 552 - /> 553 - <DataView 554 - label={label[0]} 555 - data={LABELS[label[0] as keyof typeof LABELS]} 556 - /> 557 - <DataView 558 - label="Profile Moderation Data" 559 - data={profileModeration} 560 - /> 561 - <DataView label="Post Moderation Data" data={postModeration} /> 562 - </> 563 - )} 564 - </View> 556 + {view[0] === 'data' && ( 557 + <> 558 + <ModerationUIView 559 + label="Profile Moderation UI" 560 + mod={profileModeration} 561 + /> 562 + <ModerationUIView 563 + label="Post Moderation UI" 564 + mod={postModeration} 565 + /> 566 + <DataView 567 + label={label[0]} 568 + data={LABELS[label[0] as keyof typeof LABELS]} 569 + /> 570 + <DataView 571 + label="Profile Moderation Data" 572 + data={profileModeration} 573 + /> 574 + <DataView 575 + label="Post Moderation Data" 576 + data={postModeration} 577 + /> 578 + </> 579 + )} 580 + </View> 565 581 566 - <View style={{height: 400}} /> 567 - </CenteredView> 568 - </ScrollView> 569 - </moderationOptsOverrideContext.Provider> 582 + <View style={{height: 400}} /> 583 + </CenteredView> 584 + </ScrollView> 585 + </moderationOptsOverrideContext.Provider> 586 + </Layout.Screen> 570 587 ) 571 588 } 572 589
+3 -5
src/view/screens/Feeds.tsx
··· 40 40 import {FilterTimeline_Stroke2_Corner0_Rounded as FilterTimeline} from '#/components/icons/FilterTimeline' 41 41 import {ListMagnifyingGlass_Stroke2_Corner0_Rounded} from '#/components/icons/ListMagnifyingGlass' 42 42 import {ListSparkle_Stroke2_Corner0_Rounded} from '#/components/icons/ListSparkle' 43 + import * as Layout from '#/components/Layout' 43 44 import * as ListCard from '#/components/ListCard' 44 45 45 46 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Feeds'> ··· 545 546 ) 546 547 547 548 return ( 548 - <View style={[pal.view, styles.container]}> 549 + <Layout.Screen testID="FeedsScreen"> 549 550 {isMobile && ( 550 551 <ViewHeader 551 552 title={_(msg`Feeds`)} ··· 582 583 accessibilityHint="" 583 584 /> 584 585 )} 585 - </View> 586 + </Layout.Screen> 586 587 ) 587 588 } 588 589 ··· 768 769 } 769 770 770 771 const styles = StyleSheet.create({ 771 - container: { 772 - flex: 1, 773 - }, 774 772 list: { 775 773 height: '100%', 776 774 },
+12 -9
src/view/screens/Home.tsx
··· 1 1 import React from 'react' 2 - import {ActivityIndicator, StyleSheet, View} from 'react-native' 2 + import {ActivityIndicator, StyleSheet} from 'react-native' 3 3 import {useFocusEffect} from '@react-navigation/native' 4 4 5 5 import {PROD_DEFAULT_FEED} from '#/lib/constants' ··· 23 23 import {useLoggedOutViewControls} from '#/state/shell/logged-out' 24 24 import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed' 25 25 import {FeedPage} from '#/view/com/feeds/FeedPage' 26 + import {HomeHeader} from '#/view/com/home/HomeHeader' 26 27 import {Pager, PagerRef, RenderTabBarFnProps} from '#/view/com/pager/Pager' 27 28 import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState' 28 29 import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState' 29 30 import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed' 30 31 import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned' 31 - import {HomeHeader} from '../com/home/HomeHeader' 32 + import * as Layout from '#/components/Layout' 32 33 33 34 type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home' | 'Start'> 34 35 export function HomeScreen(props: Props) { ··· 70 71 71 72 if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) { 72 73 return ( 73 - <HomeScreenReady 74 - {...props} 75 - preferences={preferences} 76 - pinnedFeedInfos={pinnedFeedInfos} 77 - /> 74 + <Layout.Screen testID="HomeScreen"> 75 + <HomeScreenReady 76 + {...props} 77 + preferences={preferences} 78 + pinnedFeedInfos={pinnedFeedInfos} 79 + /> 80 + </Layout.Screen> 78 81 ) 79 82 } else { 80 83 return ( 81 - <View style={styles.loading}> 84 + <Layout.Screen style={styles.loading}> 82 85 <ActivityIndicator size="large" /> 83 - </View> 86 + </Layout.Screen> 84 87 ) 85 88 } 86 89 }
+212 -209
src/view/screens/LanguageSettings.tsx
··· 19 19 import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences' 20 20 import {useSetMinimalShellMode} from '#/state/shell' 21 21 import {Button} from '#/view/com/util/forms/Button' 22 + import {Text} from '#/view/com/util/text/Text' 22 23 import {ViewHeader} from '#/view/com/util/ViewHeader' 23 24 import {CenteredView} from '#/view/com/util/Views' 24 - import {Text} from '../com/util/text/Text' 25 + import * as Layout from '#/components/Layout' 25 26 26 27 type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'> 27 28 ··· 76 77 }, [langPrefs.contentLanguages]) 77 78 78 79 return ( 79 - <CenteredView 80 - style={[ 81 - pal.view, 82 - pal.border, 83 - styles.container, 84 - isTabletOrDesktop && styles.desktopContainer, 85 - ]}> 86 - <ViewHeader title={_(msg`Language Settings`)} showOnDesktop /> 80 + <Layout.Screen testID="PreferencesLanguagesScreen"> 81 + <CenteredView 82 + style={[ 83 + pal.view, 84 + pal.border, 85 + styles.container, 86 + isTabletOrDesktop && styles.desktopContainer, 87 + ]}> 88 + <ViewHeader title={_(msg`Language Settings`)} showOnDesktop /> 87 89 88 - <View style={{paddingTop: 20, paddingHorizontal: 20}}> 89 - {/* APP LANGUAGE */} 90 - <View style={{paddingBottom: 20}}> 91 - <Text type="title-sm" style={[pal.text, s.pb5]}> 92 - <Trans>App Language</Trans> 93 - </Text> 94 - <Text style={[pal.text, s.pb10]}> 95 - <Trans> 96 - Select your app language for the default text to display in the 97 - app. 98 - </Trans> 99 - </Text> 90 + <View style={{paddingTop: 20, paddingHorizontal: 20}}> 91 + {/* APP LANGUAGE */} 92 + <View style={{paddingBottom: 20}}> 93 + <Text type="title-sm" style={[pal.text, s.pb5]}> 94 + <Trans>App Language</Trans> 95 + </Text> 96 + <Text style={[pal.text, s.pb10]}> 97 + <Trans> 98 + Select your app language for the default text to display in the 99 + app. 100 + </Trans> 101 + </Text> 100 102 101 - <View style={{position: 'relative'}}> 102 - <RNPickerSelect 103 - placeholder={{}} 104 - value={sanitizeAppLanguageSetting(langPrefs.appLanguage)} 105 - onValueChange={onChangeAppLanguage} 106 - items={APP_LANGUAGES.filter(l => Boolean(l.code2)).map(l => ({ 107 - label: l.name, 108 - value: l.code2, 109 - key: l.code2, 110 - }))} 111 - style={{ 112 - inputAndroid: { 113 - backgroundColor: pal.viewLight.backgroundColor, 114 - color: pal.text.color, 115 - fontSize: 14, 116 - letterSpacing: 0.5, 117 - fontWeight: '600', 118 - paddingHorizontal: 14, 119 - paddingVertical: 8, 120 - borderRadius: 24, 121 - }, 122 - inputIOS: { 123 - backgroundColor: pal.viewLight.backgroundColor, 124 - color: pal.text.color, 125 - fontSize: 14, 126 - letterSpacing: 0.5, 127 - fontWeight: '600', 128 - paddingHorizontal: 14, 129 - paddingVertical: 8, 130 - borderRadius: 24, 131 - }, 103 + <View style={{position: 'relative'}}> 104 + <RNPickerSelect 105 + placeholder={{}} 106 + value={sanitizeAppLanguageSetting(langPrefs.appLanguage)} 107 + onValueChange={onChangeAppLanguage} 108 + items={APP_LANGUAGES.filter(l => Boolean(l.code2)).map(l => ({ 109 + label: l.name, 110 + value: l.code2, 111 + key: l.code2, 112 + }))} 113 + style={{ 114 + inputAndroid: { 115 + backgroundColor: pal.viewLight.backgroundColor, 116 + color: pal.text.color, 117 + fontSize: 14, 118 + letterSpacing: 0.5, 119 + fontWeight: '600', 120 + paddingHorizontal: 14, 121 + paddingVertical: 8, 122 + borderRadius: 24, 123 + }, 124 + inputIOS: { 125 + backgroundColor: pal.viewLight.backgroundColor, 126 + color: pal.text.color, 127 + fontSize: 14, 128 + letterSpacing: 0.5, 129 + fontWeight: '600', 130 + paddingHorizontal: 14, 131 + paddingVertical: 8, 132 + borderRadius: 24, 133 + }, 134 + 135 + inputWeb: { 136 + cursor: 'pointer', 137 + // @ts-ignore web only 138 + '-moz-appearance': 'none', 139 + '-webkit-appearance': 'none', 140 + appearance: 'none', 141 + outline: 0, 142 + borderWidth: 0, 143 + backgroundColor: pal.viewLight.backgroundColor, 144 + color: pal.text.color, 145 + fontSize: 14, 146 + fontFamily: 'inherit', 147 + letterSpacing: 0.5, 148 + fontWeight: '600', 149 + paddingHorizontal: 14, 150 + paddingVertical: 8, 151 + borderRadius: 24, 152 + }, 153 + }} 154 + /> 132 155 133 - inputWeb: { 134 - cursor: 'pointer', 135 - // @ts-ignore web only 136 - '-moz-appearance': 'none', 137 - '-webkit-appearance': 'none', 138 - appearance: 'none', 139 - outline: 0, 140 - borderWidth: 0, 156 + <View 157 + style={{ 158 + position: 'absolute', 159 + top: 1, 160 + right: 1, 161 + bottom: 1, 162 + width: 40, 141 163 backgroundColor: pal.viewLight.backgroundColor, 142 - color: pal.text.color, 143 - fontSize: 14, 144 - fontFamily: 'inherit', 145 - letterSpacing: 0.5, 146 - fontWeight: '600', 147 - paddingHorizontal: 14, 148 - paddingVertical: 8, 149 164 borderRadius: 24, 150 - }, 151 - }} 152 - /> 153 - 154 - <View 155 - style={{ 156 - position: 'absolute', 157 - top: 1, 158 - right: 1, 159 - bottom: 1, 160 - width: 40, 161 - backgroundColor: pal.viewLight.backgroundColor, 162 - borderRadius: 24, 163 - pointerEvents: 'none', 164 - alignItems: 'center', 165 - justifyContent: 'center', 166 - }}> 167 - <FontAwesomeIcon 168 - icon="chevron-down" 169 - style={pal.text as FontAwesomeIconStyle} 170 - /> 165 + pointerEvents: 'none', 166 + alignItems: 'center', 167 + justifyContent: 'center', 168 + }}> 169 + <FontAwesomeIcon 170 + icon="chevron-down" 171 + style={pal.text as FontAwesomeIconStyle} 172 + /> 173 + </View> 171 174 </View> 172 175 </View> 173 - </View> 174 176 175 - <View 176 - style={{ 177 - height: 1, 178 - backgroundColor: pal.border.borderColor, 179 - marginBottom: 20, 180 - }} 181 - /> 177 + <View 178 + style={{ 179 + height: 1, 180 + backgroundColor: pal.border.borderColor, 181 + marginBottom: 20, 182 + }} 183 + /> 182 184 183 - {/* PRIMARY LANGUAGE */} 184 - <View style={{paddingBottom: 20}}> 185 - <Text type="title-sm" style={[pal.text, s.pb5]}> 186 - <Trans>Primary Language</Trans> 187 - </Text> 188 - <Text style={[pal.text, s.pb10]}> 189 - <Trans> 190 - Select your preferred language for translations in your feed. 191 - </Trans> 192 - </Text> 185 + {/* PRIMARY LANGUAGE */} 186 + <View style={{paddingBottom: 20}}> 187 + <Text type="title-sm" style={[pal.text, s.pb5]}> 188 + <Trans>Primary Language</Trans> 189 + </Text> 190 + <Text style={[pal.text, s.pb10]}> 191 + <Trans> 192 + Select your preferred language for translations in your feed. 193 + </Trans> 194 + </Text> 195 + 196 + <View style={{position: 'relative'}}> 197 + <RNPickerSelect 198 + placeholder={{}} 199 + value={langPrefs.primaryLanguage} 200 + onValueChange={onChangePrimaryLanguage} 201 + items={LANGUAGES.filter(l => Boolean(l.code2)).map(l => ({ 202 + label: l.name, 203 + value: l.code2, 204 + key: l.code2 + l.code3, 205 + }))} 206 + style={{ 207 + inputAndroid: { 208 + backgroundColor: pal.viewLight.backgroundColor, 209 + color: pal.text.color, 210 + fontSize: 14, 211 + letterSpacing: 0.5, 212 + fontWeight: '600', 213 + paddingHorizontal: 14, 214 + paddingVertical: 8, 215 + borderRadius: 24, 216 + }, 217 + inputIOS: { 218 + backgroundColor: pal.viewLight.backgroundColor, 219 + color: pal.text.color, 220 + fontSize: 14, 221 + letterSpacing: 0.5, 222 + fontWeight: '600', 223 + paddingHorizontal: 14, 224 + paddingVertical: 8, 225 + borderRadius: 24, 226 + }, 227 + inputWeb: { 228 + cursor: 'pointer', 229 + // @ts-ignore web only 230 + '-moz-appearance': 'none', 231 + '-webkit-appearance': 'none', 232 + appearance: 'none', 233 + outline: 0, 234 + borderWidth: 0, 235 + backgroundColor: pal.viewLight.backgroundColor, 236 + color: pal.text.color, 237 + fontSize: 14, 238 + fontFamily: 'inherit', 239 + letterSpacing: 0.5, 240 + fontWeight: '600', 241 + paddingHorizontal: 14, 242 + paddingVertical: 8, 243 + borderRadius: 24, 244 + }, 245 + }} 246 + /> 193 247 194 - <View style={{position: 'relative'}}> 195 - <RNPickerSelect 196 - placeholder={{}} 197 - value={langPrefs.primaryLanguage} 198 - onValueChange={onChangePrimaryLanguage} 199 - items={LANGUAGES.filter(l => Boolean(l.code2)).map(l => ({ 200 - label: l.name, 201 - value: l.code2, 202 - key: l.code2 + l.code3, 203 - }))} 204 - style={{ 205 - inputAndroid: { 206 - backgroundColor: pal.viewLight.backgroundColor, 207 - color: pal.text.color, 208 - fontSize: 14, 209 - letterSpacing: 0.5, 210 - fontWeight: '600', 211 - paddingHorizontal: 14, 212 - paddingVertical: 8, 213 - borderRadius: 24, 214 - }, 215 - inputIOS: { 248 + <View 249 + style={{ 250 + position: 'absolute', 251 + top: 1, 252 + right: 1, 253 + bottom: 1, 254 + width: 40, 216 255 backgroundColor: pal.viewLight.backgroundColor, 217 - color: pal.text.color, 218 - fontSize: 14, 219 - letterSpacing: 0.5, 220 - fontWeight: '600', 221 - paddingHorizontal: 14, 222 - paddingVertical: 8, 223 256 borderRadius: 24, 224 - }, 225 - inputWeb: { 226 - cursor: 'pointer', 227 - // @ts-ignore web only 228 - '-moz-appearance': 'none', 229 - '-webkit-appearance': 'none', 230 - appearance: 'none', 231 - outline: 0, 232 - borderWidth: 0, 233 - backgroundColor: pal.viewLight.backgroundColor, 234 - color: pal.text.color, 235 - fontSize: 14, 236 - fontFamily: 'inherit', 237 - letterSpacing: 0.5, 238 - fontWeight: '600', 239 - paddingHorizontal: 14, 240 - paddingVertical: 8, 241 - borderRadius: 24, 242 - }, 243 - }} 244 - /> 257 + pointerEvents: 'none', 258 + alignItems: 'center', 259 + justifyContent: 'center', 260 + }}> 261 + <FontAwesomeIcon 262 + icon="chevron-down" 263 + style={pal.text as FontAwesomeIconStyle} 264 + /> 265 + </View> 266 + </View> 267 + </View> 268 + 269 + <View 270 + style={{ 271 + height: 1, 272 + backgroundColor: pal.border.borderColor, 273 + marginBottom: 20, 274 + }} 275 + /> 276 + 277 + {/* CONTENT LANGUAGES */} 278 + <View style={{paddingBottom: 20}}> 279 + <Text type="title-sm" style={[pal.text, s.pb5]}> 280 + <Trans>Content Languages</Trans> 281 + </Text> 282 + <Text style={[pal.text, s.pb10]}> 283 + <Trans> 284 + Select which languages you want your subscribed feeds to 285 + include. If none are selected, all languages will be shown. 286 + </Trans> 287 + </Text> 245 288 246 - <View 247 - style={{ 248 - position: 'absolute', 249 - top: 1, 250 - right: 1, 251 - bottom: 1, 252 - width: 40, 253 - backgroundColor: pal.viewLight.backgroundColor, 254 - borderRadius: 24, 255 - pointerEvents: 'none', 256 - alignItems: 'center', 257 - justifyContent: 'center', 258 - }}> 289 + <Button 290 + type="default" 291 + onPress={onPressContentLanguages} 292 + style={styles.button}> 259 293 <FontAwesomeIcon 260 - icon="chevron-down" 294 + icon={myLanguages.length ? 'check' : 'plus'} 261 295 style={pal.text as FontAwesomeIconStyle} 262 296 /> 263 - </View> 297 + <Text 298 + type="button" 299 + style={[pal.text, {flexShrink: 1, overflow: 'hidden'}]} 300 + numberOfLines={1}> 301 + {myLanguages.length ? myLanguages : _(msg`Select languages`)} 302 + </Text> 303 + </Button> 264 304 </View> 265 305 </View> 266 - 267 - <View 268 - style={{ 269 - height: 1, 270 - backgroundColor: pal.border.borderColor, 271 - marginBottom: 20, 272 - }} 273 - /> 274 - 275 - {/* CONTENT LANGUAGES */} 276 - <View style={{paddingBottom: 20}}> 277 - <Text type="title-sm" style={[pal.text, s.pb5]}> 278 - <Trans>Content Languages</Trans> 279 - </Text> 280 - <Text style={[pal.text, s.pb10]}> 281 - <Trans> 282 - Select which languages you want your subscribed feeds to include. 283 - If none are selected, all languages will be shown. 284 - </Trans> 285 - </Text> 286 - 287 - <Button 288 - type="default" 289 - onPress={onPressContentLanguages} 290 - style={styles.button}> 291 - <FontAwesomeIcon 292 - icon={myLanguages.length ? 'check' : 'plus'} 293 - style={pal.text as FontAwesomeIconStyle} 294 - /> 295 - <Text 296 - type="button" 297 - style={[pal.text, {flexShrink: 1, overflow: 'hidden'}]} 298 - numberOfLines={1}> 299 - {myLanguages.length ? myLanguages : _(msg`Select languages`)} 300 - </Text> 301 - </Button> 302 - </View> 303 - </View> 304 - </CenteredView> 306 + </CenteredView> 307 + </Layout.Screen> 305 308 ) 306 309 } 307 310
+3 -2
src/view/screens/Lists.tsx
··· 16 16 import {Button} from '#/view/com/util/forms/Button' 17 17 import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' 18 18 import {Text} from '#/view/com/util/text/Text' 19 + import * as Layout from '#/components/Layout' 19 20 20 21 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Lists'> 21 22 export function ListsScreen({}: Props) { ··· 48 49 }, [openModal, navigation]) 49 50 50 51 return ( 51 - <View style={s.hContentRegion} testID="listsScreen"> 52 + <Layout.Screen testID="listsScreen"> 52 53 <SimpleViewHeader 53 54 showBackButton={isMobile} 54 55 style={[ ··· 86 87 </View> 87 88 </SimpleViewHeader> 88 89 <MyLists filter="curate" style={s.flexGrow1} /> 89 - </View> 90 + </Layout.Screen> 90 91 ) 91 92 }
+9 -8
src/view/screens/Log.tsx
··· 5 5 import {useLingui} from '@lingui/react' 6 6 import {useFocusEffect} from '@react-navigation/native' 7 7 8 + import {usePalette} from '#/lib/hooks/usePalette' 8 9 import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo' 10 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 11 + import {s} from '#/lib/styles' 9 12 import {getEntries} from '#/logger/logDump' 10 13 import {useTickEveryMinute} from '#/state/shell' 11 14 import {useSetMinimalShellMode} from '#/state/shell' 12 - import {usePalette} from 'lib/hooks/usePalette' 13 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 14 - import {s} from 'lib/styles' 15 - import {Text} from '../com/util/text/Text' 16 - import {ViewHeader} from '../com/util/ViewHeader' 17 - import {ScrollView} from '../com/util/Views' 15 + import {Text} from '#/view/com/util/text/Text' 16 + import {ViewHeader} from '#/view/com/util/ViewHeader' 17 + import {ScrollView} from '#/view/com/util/Views' 18 + import * as Layout from '#/components/Layout' 18 19 19 20 export function LogScreen({}: NativeStackScreenProps< 20 21 CommonNavigatorParams, ··· 42 43 } 43 44 44 45 return ( 45 - <View style={[s.flex1]}> 46 + <Layout.Screen> 46 47 <ViewHeader title="Log" /> 47 48 <ScrollView style={s.flex1}> 48 49 {getEntries() ··· 91 92 })} 92 93 <View style={s.footerSpacer} /> 93 94 </ScrollView> 94 - </View> 95 + </Layout.Screen> 95 96 ) 96 97 } 97 98
+74 -71
src/view/screens/ModerationBlockedAccounts.tsx
··· 20 20 import {useMyBlockedAccountsQuery} from '#/state/queries/my-blocked-accounts' 21 21 import {useSetMinimalShellMode} from '#/state/shell' 22 22 import {ProfileCard} from '#/view/com/profile/ProfileCard' 23 + import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' 24 + import {Text} from '#/view/com/util/text/Text' 25 + import {ViewHeader} from '#/view/com/util/ViewHeader' 23 26 import {CenteredView} from '#/view/com/util/Views' 24 - import {ErrorScreen} from '../com/util/error/ErrorScreen' 25 - import {Text} from '../com/util/text/Text' 26 - import {ViewHeader} from '../com/util/ViewHeader' 27 + import * as Layout from '#/components/Layout' 27 28 28 29 type Props = NativeStackScreenProps< 29 30 CommonNavigatorParams, ··· 95 96 /> 96 97 ) 97 98 return ( 98 - <CenteredView 99 - style={[ 100 - styles.container, 101 - isTabletOrDesktop && styles.containerDesktop, 102 - pal.view, 103 - pal.border, 104 - ]} 105 - testID="blockedAccountsScreen"> 106 - <ViewHeader title={_(msg`Blocked Accounts`)} showOnDesktop /> 107 - <Text 108 - type="sm" 99 + <Layout.Screen testID="blockedAccountsScreen"> 100 + <CenteredView 109 101 style={[ 110 - styles.description, 111 - pal.text, 112 - isTabletOrDesktop && styles.descriptionDesktop, 113 - ]}> 114 - <Trans> 115 - Blocked accounts cannot reply in your threads, mention you, or 116 - otherwise interact with you. You will not see their content and they 117 - will be prevented from seeing yours. 118 - </Trans> 119 - </Text> 120 - {isEmpty ? ( 121 - <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}> 122 - {isError ? ( 123 - <ErrorScreen 124 - title="Oops!" 125 - message={cleanError(error)} 126 - onPressTryAgain={refetch} 127 - /> 128 - ) : ( 129 - <View style={[styles.empty, pal.viewLight]}> 130 - <Text type="lg" style={[pal.text, styles.emptyText]}> 131 - <Trans> 132 - You have not blocked any accounts yet. To block an account, go 133 - to their profile and select "Block account" from the menu on 134 - their account. 135 - </Trans> 136 - </Text> 137 - </View> 138 - )} 139 - </View> 140 - ) : ( 141 - <FlatList 142 - style={[!isTabletOrDesktop && styles.flex1]} 143 - data={profiles} 144 - keyExtractor={(item: ActorDefs.ProfileView) => item.did} 145 - refreshControl={ 146 - <RefreshControl 147 - refreshing={isPTRing} 148 - onRefresh={onRefresh} 149 - tintColor={pal.colors.text} 150 - titleColor={pal.colors.text} 151 - /> 152 - } 153 - onEndReached={onEndReached} 154 - renderItem={renderItem} 155 - initialNumToRender={15} 156 - // FIXME(dan) 102 + styles.container, 103 + isTabletOrDesktop && styles.containerDesktop, 104 + pal.view, 105 + pal.border, 106 + ]} 107 + testID="blockedAccountsScreen"> 108 + <ViewHeader title={_(msg`Blocked Accounts`)} showOnDesktop /> 109 + <Text 110 + type="sm" 111 + style={[ 112 + styles.description, 113 + pal.text, 114 + isTabletOrDesktop && styles.descriptionDesktop, 115 + ]}> 116 + <Trans> 117 + Blocked accounts cannot reply in your threads, mention you, or 118 + otherwise interact with you. You will not see their content and they 119 + will be prevented from seeing yours. 120 + </Trans> 121 + </Text> 122 + {isEmpty ? ( 123 + <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}> 124 + {isError ? ( 125 + <ErrorScreen 126 + title="Oops!" 127 + message={cleanError(error)} 128 + onPressTryAgain={refetch} 129 + /> 130 + ) : ( 131 + <View style={[styles.empty, pal.viewLight]}> 132 + <Text type="lg" style={[pal.text, styles.emptyText]}> 133 + <Trans> 134 + You have not blocked any accounts yet. To block an account, 135 + go to their profile and select "Block account" from the menu 136 + on their account. 137 + </Trans> 138 + </Text> 139 + </View> 140 + )} 141 + </View> 142 + ) : ( 143 + <FlatList 144 + style={[!isTabletOrDesktop && styles.flex1]} 145 + data={profiles} 146 + keyExtractor={(item: ActorDefs.ProfileView) => item.did} 147 + refreshControl={ 148 + <RefreshControl 149 + refreshing={isPTRing} 150 + onRefresh={onRefresh} 151 + tintColor={pal.colors.text} 152 + titleColor={pal.colors.text} 153 + /> 154 + } 155 + onEndReached={onEndReached} 156 + renderItem={renderItem} 157 + initialNumToRender={15} 158 + // FIXME(dan) 157 159 158 - ListFooterComponent={() => ( 159 - <View style={styles.footer}> 160 - {(isFetching || isFetchingNextPage) && <ActivityIndicator />} 161 - </View> 162 - )} 163 - // @ts-ignore our .web version only -prf 164 - desktopFixedHeight 165 - /> 166 - )} 167 - </CenteredView> 160 + ListFooterComponent={() => ( 161 + <View style={styles.footer}> 162 + {(isFetching || isFetchingNextPage) && <ActivityIndicator />} 163 + </View> 164 + )} 165 + // @ts-ignore our .web version only -prf 166 + desktopFixedHeight 167 + /> 168 + )} 169 + </CenteredView> 170 + </Layout.Screen> 168 171 ) 169 172 } 170 173
+3 -2
src/view/screens/ModerationModlists.tsx
··· 16 16 import {Button} from '#/view/com/util/forms/Button' 17 17 import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' 18 18 import {Text} from '#/view/com/util/text/Text' 19 + import * as Layout from '#/components/Layout' 19 20 20 21 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ModerationModlists'> 21 22 export function ModerationModlistsScreen({}: Props) { ··· 48 49 }, [openModal, navigation]) 49 50 50 51 return ( 51 - <View style={s.hContentRegion} testID="moderationModlistsScreen"> 52 + <Layout.Screen testID="moderationModlistsScreen"> 52 53 <SimpleViewHeader 53 54 showBackButton={isMobile} 54 55 style={ ··· 82 83 </View> 83 84 </SimpleViewHeader> 84 85 <MyLists filter="mod" style={s.flexGrow1} /> 85 - </View> 86 + </Layout.Screen> 86 87 ) 87 88 }
+73 -70
src/view/screens/ModerationMutedAccounts.tsx
··· 20 20 import {useMyMutedAccountsQuery} from '#/state/queries/my-muted-accounts' 21 21 import {useSetMinimalShellMode} from '#/state/shell' 22 22 import {ProfileCard} from '#/view/com/profile/ProfileCard' 23 + import {ErrorScreen} from '#/view/com/util/error/ErrorScreen' 24 + import {Text} from '#/view/com/util/text/Text' 25 + import {ViewHeader} from '#/view/com/util/ViewHeader' 23 26 import {CenteredView} from '#/view/com/util/Views' 24 - import {ErrorScreen} from '../com/util/error/ErrorScreen' 25 - import {Text} from '../com/util/text/Text' 26 - import {ViewHeader} from '../com/util/ViewHeader' 27 + import * as Layout from '#/components/Layout' 27 28 28 29 type Props = NativeStackScreenProps< 29 30 CommonNavigatorParams, ··· 95 96 /> 96 97 ) 97 98 return ( 98 - <CenteredView 99 - style={[ 100 - styles.container, 101 - isTabletOrDesktop && styles.containerDesktop, 102 - pal.view, 103 - pal.border, 104 - ]} 105 - testID="mutedAccountsScreen"> 106 - <ViewHeader title={_(msg`Muted Accounts`)} showOnDesktop /> 107 - <Text 108 - type="sm" 99 + <Layout.Screen testID="mutedAccountsScreen"> 100 + <CenteredView 109 101 style={[ 110 - styles.description, 111 - pal.text, 112 - isTabletOrDesktop && styles.descriptionDesktop, 113 - ]}> 114 - <Trans> 115 - Muted accounts have their posts removed from your feed and from your 116 - notifications. Mutes are completely private. 117 - </Trans> 118 - </Text> 119 - {isEmpty ? ( 120 - <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}> 121 - {isError ? ( 122 - <ErrorScreen 123 - title="Oops!" 124 - message={cleanError(error)} 125 - onPressTryAgain={refetch} 126 - /> 127 - ) : ( 128 - <View style={[styles.empty, pal.viewLight]}> 129 - <Text type="lg" style={[pal.text, styles.emptyText]}> 130 - <Trans> 131 - You have not muted any accounts yet. To mute an account, go to 132 - their profile and select "Mute account" from the menu on their 133 - account. 134 - </Trans> 135 - </Text> 136 - </View> 137 - )} 138 - </View> 139 - ) : ( 140 - <FlatList 141 - style={[!isTabletOrDesktop && styles.flex1]} 142 - data={profiles} 143 - keyExtractor={item => item.did} 144 - refreshControl={ 145 - <RefreshControl 146 - refreshing={isPTRing} 147 - onRefresh={onRefresh} 148 - tintColor={pal.colors.text} 149 - titleColor={pal.colors.text} 150 - /> 151 - } 152 - onEndReached={onEndReached} 153 - renderItem={renderItem} 154 - initialNumToRender={15} 155 - // FIXME(dan) 102 + styles.container, 103 + isTabletOrDesktop && styles.containerDesktop, 104 + pal.view, 105 + pal.border, 106 + ]} 107 + testID="mutedAccountsScreen"> 108 + <ViewHeader title={_(msg`Muted Accounts`)} showOnDesktop /> 109 + <Text 110 + type="sm" 111 + style={[ 112 + styles.description, 113 + pal.text, 114 + isTabletOrDesktop && styles.descriptionDesktop, 115 + ]}> 116 + <Trans> 117 + Muted accounts have their posts removed from your feed and from your 118 + notifications. Mutes are completely private. 119 + </Trans> 120 + </Text> 121 + {isEmpty ? ( 122 + <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}> 123 + {isError ? ( 124 + <ErrorScreen 125 + title="Oops!" 126 + message={cleanError(error)} 127 + onPressTryAgain={refetch} 128 + /> 129 + ) : ( 130 + <View style={[styles.empty, pal.viewLight]}> 131 + <Text type="lg" style={[pal.text, styles.emptyText]}> 132 + <Trans> 133 + You have not muted any accounts yet. To mute an account, go 134 + to their profile and select "Mute account" from the menu on 135 + their account. 136 + </Trans> 137 + </Text> 138 + </View> 139 + )} 140 + </View> 141 + ) : ( 142 + <FlatList 143 + style={[!isTabletOrDesktop && styles.flex1]} 144 + data={profiles} 145 + keyExtractor={item => item.did} 146 + refreshControl={ 147 + <RefreshControl 148 + refreshing={isPTRing} 149 + onRefresh={onRefresh} 150 + tintColor={pal.colors.text} 151 + titleColor={pal.colors.text} 152 + /> 153 + } 154 + onEndReached={onEndReached} 155 + renderItem={renderItem} 156 + initialNumToRender={15} 157 + // FIXME(dan) 156 158 157 - ListFooterComponent={() => ( 158 - <View style={styles.footer}> 159 - {(isFetching || isFetchingNextPage) && <ActivityIndicator />} 160 - </View> 161 - )} 162 - // @ts-ignore our .web version only -prf 163 - desktopFixedHeight 164 - /> 165 - )} 166 - </CenteredView> 159 + ListFooterComponent={() => ( 160 + <View style={styles.footer}> 161 + {(isFetching || isFetchingNextPage) && <ActivityIndicator />} 162 + </View> 163 + )} 164 + // @ts-ignore our .web version only -prf 165 + desktopFixedHeight 166 + /> 167 + )} 168 + </CenteredView> 169 + </Layout.Screen> 167 170 ) 168 171 } 169 172
+13 -11
src/view/screens/NotFound.tsx
··· 1 1 import React from 'react' 2 2 import {StyleSheet, View} from 'react-native' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 3 5 import { 4 - useNavigation, 5 6 StackActions, 6 7 useFocusEffect, 8 + useNavigation, 7 9 } from '@react-navigation/native' 8 - import {ViewHeader} from '../com/util/ViewHeader' 9 - import {Text} from '../com/util/text/Text' 10 - import {Button} from 'view/com/util/forms/Button' 11 - import {NavigationProp} from 'lib/routes/types' 12 - import {usePalette} from 'lib/hooks/usePalette' 13 - import {s} from 'lib/styles' 10 + 11 + import {usePalette} from '#/lib/hooks/usePalette' 12 + import {NavigationProp} from '#/lib/routes/types' 13 + import {s} from '#/lib/styles' 14 14 import {useSetMinimalShellMode} from '#/state/shell' 15 - import {Trans, msg} from '@lingui/macro' 16 - import {useLingui} from '@lingui/react' 15 + import {Button} from '#/view/com/util/forms/Button' 16 + import {Text} from '#/view/com/util/text/Text' 17 + import {ViewHeader} from '#/view/com/util/ViewHeader' 18 + import * as Layout from '#/components/Layout' 17 19 18 20 export const NotFoundScreen = () => { 19 21 const pal = usePalette('default') ··· 38 40 }, [navigation, canGoBack]) 39 41 40 42 return ( 41 - <View testID="notFoundView" style={pal.view}> 43 + <Layout.Screen testID="notFoundView"> 42 44 <ViewHeader title={_(msg`Page Not Found`)} /> 43 45 <View style={styles.container}> 44 46 <Text type="title-2xl" style={[pal.text, s.mb10]}> ··· 61 63 onPress={onPressHome} 62 64 /> 63 65 </View> 64 - </View> 66 + </Layout.Screen> 65 67 ) 66 68 } 67 69
+32 -32
src/view/screens/Notifications.tsx
··· 34 34 import {atoms as a, useTheme} from '#/alf' 35 35 import {Button} from '#/components/Button' 36 36 import {SettingsGear2_Stroke2_Corner0_Rounded as SettingsIcon} from '#/components/icons/SettingsGear2' 37 + import * as Layout from '#/components/Layout' 37 38 import {Link} from '#/components/Link' 38 39 import {Loader} from '#/components/Loader' 39 40 import {Text} from '#/components/Typography' ··· 192 193 }, [renderButton, isLoadingLatest]) 193 194 194 195 return ( 195 - <CenteredView 196 - testID="notificationsScreen" 197 - style={[s.hContentRegion, {paddingTop: 2}]} 198 - sideBorders={true}> 199 - <ViewHeader 200 - title={_(msg`Notifications`)} 201 - canGoBack={false} 202 - showBorder={true} 203 - renderButton={renderHeaderSpinner} 204 - /> 205 - <MainScrollProvider> 206 - <Feed 207 - onScrolledDownChange={setIsScrolledDown} 208 - scrollElRef={scrollElRef} 209 - ListHeaderComponent={ListHeaderComponent} 210 - overridePriorityNotifications={params?.show === 'all'} 196 + <Layout.Screen testID="notificationsScreen"> 197 + <CenteredView style={[a.flex_1, {paddingTop: 2}]} sideBorders={true}> 198 + <ViewHeader 199 + title={_(msg`Notifications`)} 200 + canGoBack={false} 201 + showBorder={true} 202 + renderButton={renderHeaderSpinner} 211 203 /> 212 - </MainScrollProvider> 213 - {(isScrolledDown || hasNew) && ( 214 - <LoadLatestBtn 215 - onPress={onPressLoadLatest} 216 - label={_(msg`Load new notifications`)} 217 - showIndicator={hasNew} 204 + <MainScrollProvider> 205 + <Feed 206 + onScrolledDownChange={setIsScrolledDown} 207 + scrollElRef={scrollElRef} 208 + ListHeaderComponent={ListHeaderComponent} 209 + overridePriorityNotifications={params?.show === 'all'} 210 + /> 211 + </MainScrollProvider> 212 + {(isScrolledDown || hasNew) && ( 213 + <LoadLatestBtn 214 + onPress={onPressLoadLatest} 215 + label={_(msg`Load new notifications`)} 216 + showIndicator={hasNew} 217 + /> 218 + )} 219 + <FAB 220 + testID="composeFAB" 221 + onPress={() => openComposer({})} 222 + icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />} 223 + accessibilityRole="button" 224 + accessibilityLabel={_(msg`New post`)} 225 + accessibilityHint="" 218 226 /> 219 - )} 220 - <FAB 221 - testID="composeFAB" 222 - onPress={() => openComposer({})} 223 - icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />} 224 - accessibilityRole="button" 225 - accessibilityLabel={_(msg`New post`)} 226 - accessibilityHint="" 227 - /> 228 - </CenteredView> 227 + </CenteredView> 228 + </Layout.Screen> 229 229 ) 230 230 }
+49 -46
src/view/screens/NotificationsSettings.tsx
··· 13 13 import {Admonition} from '#/components/Admonition' 14 14 import {Error} from '#/components/Error' 15 15 import * as Toggle from '#/components/forms/Toggle' 16 + import * as Layout from '#/components/Layout' 16 17 import {Loader} from '#/components/Loader' 17 18 import {Text} from '#/components/Typography' 18 19 ··· 35 36 : serverPriority 36 37 37 38 return ( 38 - <ScrollView stickyHeaderIndices={[0]}> 39 - <ViewHeader 40 - title={_(msg`Notification Settings`)} 41 - showOnDesktop 42 - showBorder 43 - /> 44 - {isQueryError ? ( 45 - <Error 46 - title={_(msg`Oops!`)} 47 - message={_(msg`Something went wrong!`)} 48 - onRetry={refetch} 49 - sideBorders={false} 39 + <Layout.Screen> 40 + <ScrollView stickyHeaderIndices={[0]}> 41 + <ViewHeader 42 + title={_(msg`Notification Settings`)} 43 + showOnDesktop 44 + showBorder 50 45 /> 51 - ) : ( 52 - <View style={[a.p_lg, a.gap_md]}> 53 - <Text style={[a.text_lg, a.font_bold]}> 54 - <FontAwesomeIcon icon="flask" style={t.atoms.text} />{' '} 55 - <Trans>Notification filters</Trans> 56 - </Text> 57 - <Toggle.Group 58 - label={_(msg`Priority notifications`)} 59 - type="checkbox" 60 - values={priority ? ['enabled'] : []} 61 - onChange={onChangePriority} 62 - disabled={typeof priority !== 'boolean' || isMutationPending}> 63 - <View> 64 - <Toggle.Item 65 - name="enabled" 66 - label={_(msg`Enable priority notifications`)} 67 - style={[a.justify_between, a.py_sm]}> 68 - <Toggle.LabelText> 69 - <Trans>Enable priority notifications</Trans> 70 - </Toggle.LabelText> 71 - {!data ? <Loader size="md" /> : <Toggle.Platform />} 72 - </Toggle.Item> 73 - </View> 74 - </Toggle.Group> 75 - <Admonition type="warning" style={[a.mt_sm]}> 76 - <Trans> 77 - Experimental: When this preference is enabled, you'll only receive 78 - reply and quote notifications from users you follow. We'll 79 - continue to add more controls here over time. 80 - </Trans> 81 - </Admonition> 82 - </View> 83 - )} 84 - </ScrollView> 46 + {isQueryError ? ( 47 + <Error 48 + title={_(msg`Oops!`)} 49 + message={_(msg`Something went wrong!`)} 50 + onRetry={refetch} 51 + sideBorders={false} 52 + /> 53 + ) : ( 54 + <View style={[a.p_lg, a.gap_md]}> 55 + <Text style={[a.text_lg, a.font_bold]}> 56 + <FontAwesomeIcon icon="flask" style={t.atoms.text} />{' '} 57 + <Trans>Notification filters</Trans> 58 + </Text> 59 + <Toggle.Group 60 + label={_(msg`Priority notifications`)} 61 + type="checkbox" 62 + values={priority ? ['enabled'] : []} 63 + onChange={onChangePriority} 64 + disabled={typeof priority !== 'boolean' || isMutationPending}> 65 + <View> 66 + <Toggle.Item 67 + name="enabled" 68 + label={_(msg`Enable priority notifications`)} 69 + style={[a.justify_between, a.py_sm]}> 70 + <Toggle.LabelText> 71 + <Trans>Enable priority notifications</Trans> 72 + </Toggle.LabelText> 73 + {!data ? <Loader size="md" /> : <Toggle.Platform />} 74 + </Toggle.Item> 75 + </View> 76 + </Toggle.Group> 77 + <Admonition type="warning" style={[a.mt_sm]}> 78 + <Trans> 79 + Experimental: When this preference is enabled, you'll only 80 + receive reply and quote notifications from users you follow. 81 + We'll continue to add more controls here over time. 82 + </Trans> 83 + </Admonition> 84 + </View> 85 + )} 86 + </ScrollView> 87 + </Layout.Screen> 85 88 ) 86 89 }
+8 -7
src/view/screens/PostThread.tsx
··· 2 2 import {View} from 'react-native' 3 3 import {useFocusEffect} from '@react-navigation/native' 4 4 5 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 6 + import {makeRecordUri} from '#/lib/strings/url-helpers' 5 7 import {useSetMinimalShellMode} from '#/state/shell' 6 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 7 - import {makeRecordUri} from 'lib/strings/url-helpers' 8 - import {s} from 'lib/styles' 9 - import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread' 8 + import {PostThread as PostThreadComponent} from '#/view/com/post-thread/PostThread' 9 + import {atoms as a} from '#/alf' 10 + import * as Layout from '#/components/Layout' 10 11 11 12 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'> 12 13 export function PostThreadScreen({route}: Props) { ··· 22 23 ) 23 24 24 25 return ( 25 - <View style={s.hContentRegion}> 26 - <View style={s.flex1}> 26 + <Layout.Screen testID="postThreadScreen"> 27 + <View style={a.flex_1}> 27 28 <PostThreadComponent uri={uri} /> 28 29 </View> 29 - </View> 30 + </Layout.Screen> 30 31 ) 31 32 }
+6 -6
src/view/screens/PreferencesExternalEmbeds.tsx
··· 10 10 EmbedPlayerSource, 11 11 externalEmbedLabels, 12 12 } from '#/lib/strings/embed-player' 13 - import {s} from '#/lib/styles' 14 13 import { 15 14 useExternalEmbedsPrefs, 16 15 useSetExternalEmbedPref, 17 16 } from '#/state/preferences' 18 17 import {useSetMinimalShellMode} from '#/state/shell' 19 18 import {ToggleButton} from '#/view/com/util/forms/ToggleButton' 19 + import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' 20 + import {Text} from '#/view/com/util/text/Text' 21 + import {ScrollView} from '#/view/com/util/Views' 20 22 import {atoms as a} from '#/alf' 21 - import {SimpleViewHeader} from '../com/util/SimpleViewHeader' 22 - import {Text} from '../com/util/text/Text' 23 - import {ScrollView} from '../com/util/Views' 23 + import * as Layout from '#/components/Layout' 24 24 25 25 type Props = NativeStackScreenProps< 26 26 CommonNavigatorParams, ··· 38 38 ) 39 39 40 40 return ( 41 - <View style={s.hContentRegion} testID="preferencesExternalEmbedsScreen"> 41 + <Layout.Screen testID="preferencesExternalEmbedsScreen"> 42 42 <ScrollView 43 43 // @ts-ignore web only -prf 44 44 dataSet={{'stable-gutters': 1}} ··· 81 81 /> 82 82 ))} 83 83 </ScrollView> 84 - </View> 84 + </Layout.Screen> 85 85 ) 86 86 } 87 87
+3 -2
src/view/screens/PreferencesFollowingFeed.tsx
··· 17 17 import {Text} from '#/view/com/util/text/Text' 18 18 import {ScrollView} from '#/view/com/util/Views' 19 19 import {atoms as a} from '#/alf' 20 + import * as Layout from '#/components/Layout' 20 21 21 22 type Props = NativeStackScreenProps< 22 23 CommonNavigatorParams, ··· 35 36 ) 36 37 37 38 return ( 38 - <View testID="preferencesHomeFeedScreen" style={s.hContentRegion}> 39 + <Layout.Screen testID="preferencesHomeFeedScreen"> 39 40 <ScrollView 40 41 // @ts-ignore web only -sfn 41 42 dataSet={{'stable-gutters': 1}} ··· 185 186 </View> 186 187 </View> 187 188 </ScrollView> 188 - </View> 189 + </Layout.Screen> 189 190 ) 190 191 } 191 192
+3 -2
src/view/screens/PreferencesThreads.tsx
··· 18 18 import {Text} from '#/view/com/util/text/Text' 19 19 import {ScrollView} from '#/view/com/util/Views' 20 20 import {atoms as a} from '#/alf' 21 + import * as Layout from '#/components/Layout' 21 22 22 23 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PreferencesThreads'> 23 24 export function PreferencesThreads({}: Props) { ··· 38 39 ) 39 40 40 41 return ( 41 - <View testID="preferencesThreadsScreen" style={s.hContentRegion}> 42 + <Layout.Screen testID="preferencesThreadsScreen"> 42 43 <ScrollView 43 44 // @ts-ignore web only -prf 44 45 dataSet={{'stable-gutters': 1}} ··· 134 135 <ActivityIndicator style={a.flex_1} /> 135 136 )} 136 137 </ScrollView> 137 - </View> 138 + </Layout.Screen> 138 139 ) 139 140 } 140 141
+13 -11
src/view/screens/PrivacyPolicy.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 3 5 import {useFocusEffect} from '@react-navigation/native' 4 - import {Text} from 'view/com/util/text/Text' 5 - import {TextLink} from 'view/com/util/Link' 6 - import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' 7 - import {ViewHeader} from '../com/util/ViewHeader' 8 - import {ScrollView} from 'view/com/util/Views' 9 - import {usePalette} from 'lib/hooks/usePalette' 10 - import {s} from 'lib/styles' 6 + 7 + import {usePalette} from '#/lib/hooks/usePalette' 8 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 9 + import {s} from '#/lib/styles' 11 10 import {useSetMinimalShellMode} from '#/state/shell' 12 - import {Trans, msg} from '@lingui/macro' 13 - import {useLingui} from '@lingui/react' 11 + import {TextLink} from '#/view/com/util/Link' 12 + import {Text} from '#/view/com/util/text/Text' 13 + import {ScrollView} from '#/view/com/util/Views' 14 + import * as Layout from '#/components/Layout' 15 + import {ViewHeader} from '../com/util/ViewHeader' 14 16 15 17 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PrivacyPolicy'> 16 18 export const PrivacyPolicyScreen = (_props: Props) => { ··· 25 27 ) 26 28 27 29 return ( 28 - <View> 30 + <Layout.Screen> 29 31 <ViewHeader title={_(msg`Privacy Policy`)} /> 30 32 <ScrollView style={[s.hContentRegion, pal.view]}> 31 33 <View style={[s.p20]}> ··· 42 44 </View> 43 45 <View style={s.footerSpacer} /> 44 46 </ScrollView> 45 - </View> 47 + </Layout.Screen> 46 48 ) 47 49 }
+10 -1
src/view/screens/Profile.tsx
··· 45 45 import {ProfileFeedSection} from '#/screens/Profile/Sections/Feed' 46 46 import {ProfileLabelsSection} from '#/screens/Profile/Sections/Labels' 47 47 import {web} from '#/alf' 48 + import * as Layout from '#/components/Layout' 48 49 import {ScreenHider} from '#/components/moderation/ScreenHider' 49 50 import {ProfileStarterPacks} from '#/components/StarterPack/ProfileStarterPacks' 50 51 import {navigate} from '#/Navigation' ··· 55 56 } 56 57 57 58 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'> 58 - export function ProfileScreen({route}: Props) { 59 + export function ProfileScreen(props: Props) { 60 + return ( 61 + <Layout.Screen testID="profileScreen"> 62 + <ProfileScreenInner {...props} /> 63 + </Layout.Screen> 64 + ) 65 + } 66 + 67 + function ProfileScreenInner({route}: Props) { 59 68 const {_} = useLingui() 60 69 const {currentAccount} = useSession() 61 70 const queryClient = useQueryClient()
+30 -23
src/view/screens/ProfileFeed.tsx
··· 61 61 } from '#/components/icons/Heart2' 62 62 import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' 63 63 import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash' 64 + import * as Layout from '#/components/Layout' 64 65 import {InlineLinkText} from '#/components/Link' 65 66 import * as Menu from '#/components/Menu' 66 67 import {ReportDialog, useReportDialogControl} from '#/components/ReportDialog' ··· 96 97 97 98 if (error) { 98 99 return ( 99 - <CenteredView> 100 - <View style={[pal.view, pal.border, styles.notFoundContainer]}> 101 - <Text type="title-lg" style={[pal.text, s.mb10]}> 102 - <Trans>Could not load feed</Trans> 103 - </Text> 104 - <Text type="md" style={[pal.text, s.mb20]}> 105 - {error.toString()} 106 - </Text> 100 + <Layout.Screen testID="profileFeedScreenError"> 101 + <CenteredView> 102 + <View style={[pal.view, pal.border, styles.notFoundContainer]}> 103 + <Text type="title-lg" style={[pal.text, s.mb10]}> 104 + <Trans>Could not load feed</Trans> 105 + </Text> 106 + <Text type="md" style={[pal.text, s.mb20]}> 107 + {error.toString()} 108 + </Text> 107 109 108 - <View style={{flexDirection: 'row'}}> 109 - <Button 110 - type="default" 111 - accessibilityLabel={_(msg`Go back`)} 112 - accessibilityHint={_(msg`Returns to previous page`)} 113 - onPress={onPressBack} 114 - style={{flexShrink: 1}}> 115 - <Text type="button" style={pal.text}> 116 - <Trans>Go Back</Trans> 117 - </Text> 118 - </Button> 110 + <View style={{flexDirection: 'row'}}> 111 + <Button 112 + type="default" 113 + accessibilityLabel={_(msg`Go back`)} 114 + accessibilityHint={_(msg`Returns to previous page`)} 115 + onPress={onPressBack} 116 + style={{flexShrink: 1}}> 117 + <Text type="button" style={pal.text}> 118 + <Trans>Go Back</Trans> 119 + </Text> 120 + </Button> 121 + </View> 119 122 </View> 120 - </View> 121 - </CenteredView> 123 + </CenteredView> 124 + </Layout.Screen> 122 125 ) 123 126 } 124 127 125 128 return resolvedUri ? ( 126 - <ProfileFeedScreenIntermediate feedUri={resolvedUri.uri} /> 129 + <Layout.Screen> 130 + <ProfileFeedScreenIntermediate feedUri={resolvedUri.uri} /> 131 + </Layout.Screen> 127 132 ) : ( 128 - <LoadingScreen /> 133 + <Layout.Screen> 134 + <LoadingScreen /> 135 + </Layout.Screen> 129 136 ) 130 137 } 131 138
+7 -7
src/view/screens/ProfileFeedLikedBy.tsx
··· 1 1 import React from 'react' 2 - import {View} from 'react-native' 3 2 import {msg} from '@lingui/macro' 4 3 import {useLingui} from '@lingui/react' 5 4 import {useFocusEffect} from '@react-navigation/native' 6 5 6 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 7 + import {makeRecordUri} from '#/lib/strings/url-helpers' 7 8 import {useSetMinimalShellMode} from '#/state/shell' 8 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 9 - import {makeRecordUri} from 'lib/strings/url-helpers' 10 - import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy' 11 - import {ViewHeader} from '../com/util/ViewHeader' 9 + import {PostLikedBy as PostLikedByComponent} from '#/view/com/post-thread/PostLikedBy' 10 + import {ViewHeader} from '#/view/com/util/ViewHeader' 11 + import * as Layout from '#/components/Layout' 12 12 13 13 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'> 14 14 export const ProfileFeedLikedByScreen = ({route}: Props) => { ··· 24 24 ) 25 25 26 26 return ( 27 - <View style={{flex: 1}}> 27 + <Layout.Screen testID="postLikedByScreen"> 28 28 <ViewHeader title={_(msg`Liked By`)} /> 29 29 <PostLikedByComponent uri={uri} /> 30 - </View> 30 + </Layout.Screen> 31 31 ) 32 32 }
+13 -11
src/view/screens/ProfileFollowers.tsx
··· 3 3 import {useLingui} from '@lingui/react' 4 4 import {useFocusEffect} from '@react-navigation/native' 5 5 6 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 7 + import {isWeb} from '#/platform/detection' 6 8 import {useSetMinimalShellMode} from '#/state/shell' 7 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 8 - import {isWeb} from 'platform/detection' 9 - import {CenteredView} from 'view/com/util/Views' 10 - import {atoms as a} from '#/alf' 9 + import {ProfileFollowers as ProfileFollowersComponent} from '#/view/com/profile/ProfileFollowers' 10 + import {ViewHeader} from '#/view/com/util/ViewHeader' 11 + import {CenteredView} from '#/view/com/util/Views' 12 + import * as Layout from '#/components/Layout' 11 13 import {ListHeaderDesktop} from '#/components/Lists' 12 - import {ProfileFollowers as ProfileFollowersComponent} from '../com/profile/ProfileFollowers' 13 - import {ViewHeader} from '../com/util/ViewHeader' 14 14 15 15 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'> 16 16 export const ProfileFollowersScreen = ({route}: Props) => { ··· 25 25 ) 26 26 27 27 return ( 28 - <CenteredView style={a.util_screen_outer} sideBorders={true}> 29 - <ListHeaderDesktop title={_(msg`Followers`)} /> 30 - <ViewHeader title={_(msg`Followers`)} showBorder={!isWeb} /> 31 - <ProfileFollowersComponent name={name} /> 32 - </CenteredView> 28 + <Layout.Screen testID="profileFollowersScreen"> 29 + <CenteredView sideBorders={true}> 30 + <ListHeaderDesktop title={_(msg`Followers`)} /> 31 + <ViewHeader title={_(msg`Followers`)} showBorder={!isWeb} /> 32 + <ProfileFollowersComponent name={name} /> 33 + </CenteredView> 34 + </Layout.Screen> 33 35 ) 34 36 }
+13 -11
src/view/screens/ProfileFollows.tsx
··· 3 3 import {useLingui} from '@lingui/react' 4 4 import {useFocusEffect} from '@react-navigation/native' 5 5 6 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 7 + import {isWeb} from '#/platform/detection' 6 8 import {useSetMinimalShellMode} from '#/state/shell' 7 - import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' 8 - import {isWeb} from 'platform/detection' 9 - import {CenteredView} from 'view/com/util/Views' 10 - import {atoms as a} from '#/alf' 9 + import {ProfileFollows as ProfileFollowsComponent} from '#/view/com/profile/ProfileFollows' 10 + import {ViewHeader} from '#/view/com/util/ViewHeader' 11 + import {CenteredView} from '#/view/com/util/Views' 12 + import * as Layout from '#/components/Layout' 11 13 import {ListHeaderDesktop} from '#/components/Lists' 12 - import {ProfileFollows as ProfileFollowsComponent} from '../com/profile/ProfileFollows' 13 - import {ViewHeader} from '../com/util/ViewHeader' 14 14 15 15 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'> 16 16 export const ProfileFollowsScreen = ({route}: Props) => { ··· 25 25 ) 26 26 27 27 return ( 28 - <CenteredView style={a.util_screen_outer} sideBorders={true}> 29 - <ListHeaderDesktop title={_(msg`Following`)} /> 30 - <ViewHeader title={_(msg`Following`)} showBorder={!isWeb} /> 31 - <ProfileFollowsComponent name={name} /> 32 - </CenteredView> 28 + <Layout.Screen testID="profileFollowsScreen"> 29 + <CenteredView sideBorders={true}> 30 + <ListHeaderDesktop title={_(msg`Following`)} /> 31 + <ViewHeader title={_(msg`Following`)} showBorder={!isWeb} /> 32 + <ProfileFollowsComponent name={name} /> 33 + </CenteredView> 34 + </Layout.Screen> 33 35 ) 34 36 }
+9
src/view/screens/ProfileList.tsx
··· 73 73 import {ListHiddenScreen} from '#/screens/List/ListHiddenScreen' 74 74 import {atoms as a, useTheme} from '#/alf' 75 75 import {useDialogControl} from '#/components/Dialog' 76 + import * as Layout from '#/components/Layout' 76 77 import * as Hider from '#/components/moderation/Hider' 77 78 import * as Prompt from '#/components/Prompt' 78 79 import {ReportDialog, useReportDialogControl} from '#/components/ReportDialog' ··· 87 88 88 89 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileList'> 89 90 export function ProfileListScreen(props: Props) { 91 + return ( 92 + <Layout.Screen testID="profileListScreen"> 93 + <ProfileListScreenInner {...props} /> 94 + </Layout.Screen> 95 + ) 96 + } 97 + 98 + function ProfileListScreenInner(props: Props) { 90 99 const {_} = useLingui() 91 100 const {name: handleOrDid, rkey} = props.route.params 92 101 const {data: resolvedUri, error: resolveError} = useResolveUriQuery(
+104 -118
src/view/screens/SavedFeeds.tsx
··· 32 32 import {atoms as a, useTheme} from '#/alf' 33 33 import {Button, ButtonIcon, ButtonText} from '#/components/Button' 34 34 import {FilterTimeline_Stroke2_Corner0_Rounded as FilterTimeline} from '#/components/icons/FilterTimeline' 35 + import * as Layout from '#/components/Layout' 35 36 import {Loader} from '#/components/Loader' 36 37 37 38 type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'> ··· 106 107 }, [_, isDesktop, onSaveChanges, hasUnsavedChanges, isOverwritePending]) 107 108 108 109 return ( 109 - <CenteredView 110 - style={[ 111 - s.hContentRegion, 112 - pal.border, 113 - isTabletOrDesktop && styles.desktopContainer, 114 - ]}> 115 - <ViewHeader 116 - title={_(msg`Edit My Feeds`)} 117 - showOnDesktop 118 - showBorder 119 - renderButton={renderHeaderBtn} 120 - /> 121 - <ScrollView style={s.flex1} contentContainerStyle={[styles.noBorder]}> 122 - {noSavedFeedsOfAnyType && ( 123 - <View 124 - style={[pal.border, {borderBottomWidth: StyleSheet.hairlineWidth}]}> 125 - <NoSavedFeedsOfAnyType /> 110 + <Layout.Screen> 111 + <CenteredView 112 + style={[a.util_screen_outer]} 113 + sideBorders={isTabletOrDesktop}> 114 + <ViewHeader 115 + title={_(msg`Edit My Feeds`)} 116 + showOnDesktop 117 + showBorder 118 + renderButton={renderHeaderBtn} 119 + /> 120 + <ScrollView style={[a.flex_1]} contentContainerStyle={[a.border_0]}> 121 + {noSavedFeedsOfAnyType && ( 122 + <View style={[pal.border, a.border_b]}> 123 + <NoSavedFeedsOfAnyType /> 124 + </View> 125 + )} 126 + 127 + <View style={[pal.text, pal.border, styles.title]}> 128 + <Text type="title" style={pal.text}> 129 + <Trans>Pinned Feeds</Trans> 130 + </Text> 126 131 </View> 127 - )} 128 132 129 - <View style={[pal.text, pal.border, styles.title]}> 130 - <Text type="title" style={pal.text}> 131 - <Trans>Pinned Feeds</Trans> 132 - </Text> 133 - </View> 133 + {preferences ? ( 134 + !pinnedFeeds.length ? ( 135 + <View 136 + style={[ 137 + pal.border, 138 + isMobile && s.flex1, 139 + pal.viewLight, 140 + styles.empty, 141 + ]}> 142 + <Text type="lg" style={[pal.text]}> 143 + <Trans>You don't have any pinned feeds.</Trans> 144 + </Text> 145 + </View> 146 + ) : ( 147 + pinnedFeeds.map(f => ( 148 + <ListItem 149 + key={f.id} 150 + feed={f} 151 + isPinned 152 + currentFeeds={currentFeeds} 153 + setCurrentFeeds={setCurrentFeeds} 154 + preferences={preferences} 155 + /> 156 + )) 157 + ) 158 + ) : ( 159 + <ActivityIndicator style={{marginTop: 20}} /> 160 + )} 134 161 135 - {preferences ? ( 136 - !pinnedFeeds.length ? ( 137 - <View 138 - style={[ 139 - pal.border, 140 - isMobile && s.flex1, 141 - pal.viewLight, 142 - styles.empty, 143 - ]}> 144 - <Text type="lg" style={[pal.text]}> 145 - <Trans>You don't have any pinned feeds.</Trans> 146 - </Text> 162 + {noFollowingFeed && ( 163 + <View style={[pal.border, a.border_b]}> 164 + <NoFollowingFeed /> 147 165 </View> 148 - ) : ( 149 - pinnedFeeds.map(f => ( 150 - <ListItem 151 - key={f.id} 152 - feed={f} 153 - isPinned 154 - currentFeeds={currentFeeds} 155 - setCurrentFeeds={setCurrentFeeds} 156 - preferences={preferences} 157 - /> 158 - )) 159 - ) 160 - ) : ( 161 - <ActivityIndicator style={{marginTop: 20}} /> 162 - )} 166 + )} 163 167 164 - {noFollowingFeed && ( 165 - <View 166 - style={[pal.border, {borderBottomWidth: StyleSheet.hairlineWidth}]}> 167 - <NoFollowingFeed /> 168 + <View style={[pal.text, pal.border, styles.title]}> 169 + <Text type="title" style={pal.text}> 170 + <Trans>Saved Feeds</Trans> 171 + </Text> 168 172 </View> 169 - )} 170 - 171 - <View style={[pal.text, pal.border, styles.title]}> 172 - <Text type="title" style={pal.text}> 173 - <Trans>Saved Feeds</Trans> 174 - </Text> 175 - </View> 176 - {preferences ? ( 177 - !unpinnedFeeds.length ? ( 178 - <View 179 - style={[ 180 - pal.border, 181 - isMobile && s.flex1, 182 - pal.viewLight, 183 - styles.empty, 184 - ]}> 185 - <Text type="lg" style={[pal.text]}> 186 - <Trans>You don't have any saved feeds.</Trans> 187 - </Text> 188 - </View> 173 + {preferences ? ( 174 + !unpinnedFeeds.length ? ( 175 + <View 176 + style={[ 177 + pal.border, 178 + isMobile && s.flex1, 179 + pal.viewLight, 180 + styles.empty, 181 + ]}> 182 + <Text type="lg" style={[pal.text]}> 183 + <Trans>You don't have any saved feeds.</Trans> 184 + </Text> 185 + </View> 186 + ) : ( 187 + unpinnedFeeds.map(f => ( 188 + <ListItem 189 + key={f.id} 190 + feed={f} 191 + isPinned={false} 192 + currentFeeds={currentFeeds} 193 + setCurrentFeeds={setCurrentFeeds} 194 + preferences={preferences} 195 + /> 196 + )) 197 + ) 189 198 ) : ( 190 - unpinnedFeeds.map(f => ( 191 - <ListItem 192 - key={f.id} 193 - feed={f} 194 - isPinned={false} 195 - currentFeeds={currentFeeds} 196 - setCurrentFeeds={setCurrentFeeds} 197 - preferences={preferences} 198 - /> 199 - )) 200 - ) 201 - ) : ( 202 - <ActivityIndicator style={{marginTop: 20}} /> 203 - )} 199 + <ActivityIndicator style={{marginTop: 20}} /> 200 + )} 204 201 205 - <View style={styles.footerText}> 206 - <Text type="sm" style={pal.textLight}> 207 - <Trans> 208 - Feeds are custom algorithms that users build with a little coding 209 - expertise.{' '} 210 - <TextLink 211 - type="sm" 212 - style={pal.link} 213 - href="https://github.com/bluesky-social/feed-generator" 214 - text={_(msg`See this guide`)} 215 - />{' '} 216 - for more information. 217 - </Trans> 218 - </Text> 219 - </View> 220 - <View style={{height: 100}} /> 221 - </ScrollView> 222 - </CenteredView> 202 + <View style={styles.footerText}> 203 + <Text type="sm" style={pal.textLight}> 204 + <Trans> 205 + Feeds are custom algorithms that users build with a little 206 + coding expertise.{' '} 207 + <TextLink 208 + type="sm" 209 + style={pal.link} 210 + href="https://github.com/bluesky-social/feed-generator" 211 + text={_(msg`See this guide`)} 212 + />{' '} 213 + for more information. 214 + </Trans> 215 + </Text> 216 + </View> 217 + <View style={{height: 100}} /> 218 + </ScrollView> 219 + </CenteredView> 220 + </Layout.Screen> 223 221 ) 224 222 } 225 223 ··· 434 432 } 435 433 436 434 const styles = StyleSheet.create({ 437 - desktopContainer: { 438 - borderLeftWidth: 1, 439 - borderRightWidth: 1, 440 - // @ts-ignore only rendered on web 441 - minHeight: '100vh', 442 - }, 443 435 empty: { 444 436 paddingHorizontal: 20, 445 437 paddingVertical: 20, ··· 462 454 paddingHorizontal: 26, 463 455 paddingTop: 22, 464 456 paddingBottom: 100, 465 - }, 466 - noBorder: { 467 - borderBottomWidth: 0, 468 - borderRightWidth: 0, 469 - borderLeftWidth: 0, 470 - borderTopWidth: 0, 471 457 }, 472 458 })
+5 -3
src/view/screens/Search/Explore.tsx
··· 10 10 import {msg, Trans} from '@lingui/macro' 11 11 import {useLingui} from '@lingui/react' 12 12 13 + import {cleanError} from '#/lib/strings/errors' 13 14 import {logger} from '#/logger' 14 15 import {isWeb} from '#/platform/detection' 15 16 import {useModerationOpts} from '#/state/preferences/moderation-opts' 16 17 import {useGetPopularFeedsQuery} from '#/state/queries/feed' 17 18 import {usePreferencesQuery} from '#/state/queries/preferences' 18 19 import {useSuggestedFollowsQuery} from '#/state/queries/suggested-follows' 19 - import {cleanError} from 'lib/strings/errors' 20 20 import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' 21 21 import {List} from '#/view/com/util/List' 22 - import {UserAvatar} from '#/view/com/util/UserAvatar' 23 22 import { 24 23 FeedFeedLoadingPlaceholder, 25 24 ProfileCardFeedLoadingPlaceholder, 26 - } from 'view/com/util/LoadingPlaceholder' 25 + } from '#/view/com/util/LoadingPlaceholder' 26 + import {UserAvatar} from '#/view/com/util/UserAvatar' 27 27 import {atoms as a, useTheme, ViewStyleProp} from '#/alf' 28 28 import {Button} from '#/components/Button' 29 29 import * as FeedCard from '#/components/FeedCard' ··· 564 564 [t, moderationOpts], 565 565 ) 566 566 567 + // note: actually not a screen, instead it's nested within 568 + // the search screen. so we don't need Layout.Screen 567 569 return ( 568 570 <List 569 571 data={items}
+3 -2
src/view/screens/Search/Search.tsx
··· 65 65 import {SearchInput} from '#/components/forms/SearchInput' 66 66 import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron' 67 67 import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu' 68 + import * as Layout from '#/components/Layout' 68 69 69 70 function Loader() { 70 71 const pal = usePalette('default') ··· 852 853 }, [setShowAutocomplete]) 853 854 854 855 return ( 855 - <View style={isWeb ? null : {flex: 1}}> 856 + <Layout.Screen testID="searchScreen"> 856 857 <CenteredView 857 858 style={[ 858 859 a.p_md, ··· 957 958 headerHeight={headerHeight} 958 959 /> 959 960 </View> 960 - </View> 961 + </Layout.Screen> 961 962 ) 962 963 } 963 964
+3 -2
src/view/screens/Settings/index.tsx
··· 57 57 import {useDialogControl} from '#/components/Dialog' 58 58 import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings' 59 59 import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog' 60 + import * as Layout from '#/components/Layout' 60 61 import {Email2FAToggle} from './Email2FAToggle' 61 62 import {ExportCarDialog} from './ExportCarDialog' 62 63 ··· 286 287 const {mutate: onPressDeleteChatDeclaration} = useDeleteActorDeclaration() 287 288 288 289 return ( 289 - <View style={s.hContentRegion} testID="settingsScreen"> 290 + <Layout.Screen testID="settingsScreen"> 290 291 <ExportCarDialog control={exportCarControl} /> 291 292 <BirthDateSettingsDialog control={birthdayControl} /> 292 293 ··· 919 920 </View> 920 921 <View style={s.footerSpacer} /> 921 922 </ScrollView> 922 - </View> 923 + </Layout.Screen> 923 924 ) 924 925 } 925 926
+10 -5
src/view/screens/Storybook/index.tsx
··· 7 7 import {ListContained} from '#/view/screens/Storybook/ListContained' 8 8 import {atoms as a, ThemeProvider, useTheme} from '#/alf' 9 9 import {Button, ButtonText} from '#/components/Button' 10 + import * as Layout from '#/components/Layout' 10 11 import {Admonitions} from './Admonitions' 11 12 import {Breakpoints} from './Breakpoints' 12 13 import {Buttons} from './Buttons' ··· 21 22 import {Typography} from './Typography' 22 23 23 24 export function Storybook() { 24 - if (isWeb) return <StorybookInner /> 25 - 26 25 return ( 27 - <ScrollView> 28 - <StorybookInner /> 29 - </ScrollView> 26 + <Layout.Screen> 27 + {isWeb ? ( 28 + <StorybookInner /> 29 + ) : ( 30 + <ScrollView> 31 + <StorybookInner /> 32 + </ScrollView> 33 + )} 34 + </Layout.Screen> 30 35 ) 31 36 } 32 37
+14 -13
src/view/screens/Support.tsx
··· 1 1 import React from 'react' 2 - import {View} from 'react-native' 2 + import {msg, Trans} from '@lingui/macro' 3 + import {useLingui} from '@lingui/react' 3 4 import {useFocusEffect} from '@react-navigation/native' 4 - import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' 5 - import {ViewHeader} from '../com/util/ViewHeader' 6 - import {Text} from 'view/com/util/text/Text' 7 - import {TextLink} from 'view/com/util/Link' 8 - import {CenteredView} from 'view/com/util/Views' 9 - import {usePalette} from 'lib/hooks/usePalette' 10 - import {s} from 'lib/styles' 11 - import {HELP_DESK_URL} from 'lib/constants' 5 + 6 + import {HELP_DESK_URL} from '#/lib/constants' 7 + import {usePalette} from '#/lib/hooks/usePalette' 8 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 9 + import {s} from '#/lib/styles' 12 10 import {useSetMinimalShellMode} from '#/state/shell' 13 - import {Trans, msg} from '@lingui/macro' 14 - import {useLingui} from '@lingui/react' 11 + import {TextLink} from '#/view/com/util/Link' 12 + import {Text} from '#/view/com/util/text/Text' 13 + import {ViewHeader} from '#/view/com/util/ViewHeader' 14 + import {CenteredView} from '#/view/com/util/Views' 15 + import * as Layout from '#/components/Layout' 15 16 16 17 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Support'> 17 18 export const SupportScreen = (_props: Props) => { ··· 26 27 ) 27 28 28 29 return ( 29 - <View> 30 + <Layout.Screen> 30 31 <ViewHeader title={_(msg`Support`)} /> 31 32 <CenteredView> 32 33 <Text type="title-xl" style={[pal.text, s.p20, s.pb5]}> ··· 44 45 </Trans> 45 46 </Text> 46 47 </CenteredView> 47 - </View> 48 + </Layout.Screen> 48 49 ) 49 50 }
+13 -11
src/view/screens/TermsOfService.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 3 5 import {useFocusEffect} from '@react-navigation/native' 4 - import {Text} from 'view/com/util/text/Text' 5 - import {TextLink} from 'view/com/util/Link' 6 - import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' 7 - import {ViewHeader} from '../com/util/ViewHeader' 8 - import {ScrollView} from 'view/com/util/Views' 9 - import {usePalette} from 'lib/hooks/usePalette' 10 - import {s} from 'lib/styles' 6 + 7 + import {usePalette} from '#/lib/hooks/usePalette' 8 + import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' 9 + import {s} from '#/lib/styles' 11 10 import {useSetMinimalShellMode} from '#/state/shell' 12 - import {Trans, msg} from '@lingui/macro' 13 - import {useLingui} from '@lingui/react' 11 + import {TextLink} from '#/view/com/util/Link' 12 + import {Text} from '#/view/com/util/text/Text' 13 + import {ScrollView} from '#/view/com/util/Views' 14 + import * as Layout from '#/components/Layout' 15 + import {ViewHeader} from '../com/util/ViewHeader' 14 16 15 17 type Props = NativeStackScreenProps<CommonNavigatorParams, 'TermsOfService'> 16 18 export const TermsOfServiceScreen = (_props: Props) => { ··· 25 27 ) 26 28 27 29 return ( 28 - <View> 30 + <Layout.Screen> 29 31 <ViewHeader title={_(msg`Terms of Service`)} /> 30 32 <ScrollView style={[s.hContentRegion, pal.view]}> 31 33 <View style={[s.p20]}> ··· 40 42 </View> 41 43 <View style={s.footerSpacer} /> 42 44 </ScrollView> 43 - </View> 45 + </Layout.Screen> 44 46 ) 45 47 }
+9 -19
src/view/shell/index.tsx
··· 1 1 import React from 'react' 2 - import { 3 - BackHandler, 4 - DimensionValue, 5 - StyleSheet, 6 - useWindowDimensions, 7 - View, 8 - } from 'react-native' 2 + import {BackHandler, StyleSheet, useWindowDimensions, View} from 'react-native' 9 3 import {Drawer} from 'react-native-drawer-layout' 10 4 import Animated from 'react-native-reanimated' 11 - import {useSafeAreaInsets} from 'react-native-safe-area-context' 12 5 import * as NavigationBar from 'expo-navigation-bar' 13 6 import {StatusBar} from 'expo-status-bar' 14 7 import {useNavigation, useNavigationState} from '@react-navigation/native' ··· 32 25 import {Lightbox} from '#/view/com/lightbox/Lightbox' 33 26 import {ModalsContainer} from '#/view/com/modals/Modal' 34 27 import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' 28 + import {atoms as a} from '#/alf' 35 29 import {MutedWordsDialog} from '#/components/dialogs/MutedWords' 36 30 import {SigninDialog} from '#/components/dialogs/Signin' 37 31 import {Outlet as PortalOutlet} from '#/components/Portal' ··· 46 40 const isDrawerSwipeDisabled = useIsDrawerSwipeDisabled() 47 41 const setIsDrawerOpen = useSetDrawerOpen() 48 42 const winDim = useWindowDimensions() 49 - const safeAreaInsets = useSafeAreaInsets() 50 - const containerPadding = React.useMemo( 51 - () => ({height: '100%' as DimensionValue, paddingTop: safeAreaInsets.top}), 52 - [safeAreaInsets], 53 - ) 43 + 54 44 const renderDrawerContent = React.useCallback(() => <DrawerContent />, []) 55 45 const onOpenDrawer = React.useCallback( 56 46 () => setIsDrawerOpen(true), ··· 68 58 useNotificationsHandler() 69 59 70 60 React.useEffect(() => { 71 - let listener = {remove() {}} 72 61 if (isAndroid) { 73 - listener = BackHandler.addEventListener('hardwareBackPress', () => { 62 + const listener = BackHandler.addEventListener('hardwareBackPress', () => { 74 63 return closeAnyActiveElement() 75 64 }) 76 - } 77 - return () => { 78 - listener.remove() 65 + 66 + return () => { 67 + listener.remove() 68 + } 79 69 } 80 70 }, [closeAnyActiveElement]) 81 71 ··· 102 92 103 93 return ( 104 94 <> 105 - <Animated.View style={containerPadding}> 95 + <Animated.View style={[a.h_full]}> 106 96 <ErrorBoundary> 107 97 <Drawer 108 98 renderDrawerContent={renderDrawerContent}
+8 -7
src/view/shell/index.web.tsx
··· 7 7 import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle' 8 8 import {useIntentHandler} from '#/lib/hooks/useIntentHandler' 9 9 import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock' 10 + import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 10 11 import {NavigationProp} from '#/lib/routes/types' 11 - import {colors, s} from '#/lib/styles' 12 + import {colors} from '#/lib/styles' 12 13 import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' 13 14 import {useComposerKeyboardShortcut} from '#/state/shell/composer/useComposerKeyboardShortcut' 14 15 import {useCloseAllActiveElements} from '#/state/util' 16 + import {Lightbox} from '#/view/com/lightbox/Lightbox' 17 + import {ModalsContainer} from '#/view/com/modals/Modal' 18 + import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' 19 + import {atoms as a} from '#/alf' 15 20 import {MutedWordsDialog} from '#/components/dialogs/MutedWords' 16 21 import {SigninDialog} from '#/components/dialogs/Signin' 17 22 import {Outlet as PortalOutlet} from '#/components/Portal' 18 - import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries' 19 - import {FlatNavigator, RoutesContainer} from '../../Navigation' 20 - import {Lightbox} from '../com/lightbox/Lightbox' 21 - import {ModalsContainer} from '../com/modals/Modal' 22 - import {ErrorBoundary} from '../com/util/ErrorBoundary' 23 + import {FlatNavigator, RoutesContainer} from '#/Navigation' 23 24 import {Composer} from './Composer.web' 24 25 import {DrawerContent} from './Drawer' 25 26 ··· 78 79 export const Shell: React.FC = function ShellImpl() { 79 80 const pageBg = useColorSchemeStyle(styles.bgLight, styles.bgDark) 80 81 return ( 81 - <View style={[s.hContentRegion, pageBg]}> 82 + <View style={[a.util_screen_outer, pageBg]}> 82 83 <RoutesContainer> 83 84 <ShellInner /> 84 85 </RoutesContainer>