+41
src/components/Layout.tsx
+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}
+16
-15
src/screens/Hashtag.tsx
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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>