Begin work on Header

This commit is contained in:
Eric Bailey
2025-01-16 18:56:41 -06:00
parent 4ffc952e27
commit 118e0318fe
3 changed files with 142 additions and 10 deletions
+3 -10
View File
@@ -46,6 +46,7 @@ import {useSetLightStatusBar} from '#/state/shell/light-status-bar'
import {List} from '#/view/com/util/List'
import {PostCtrls} from '#/view/com/util/post-ctrls/PostCtrls'
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
import {Header} from '#/screens/VideoFeed/Header'
import {atoms as a, ThemeProvider, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Layout from '#/components/Layout'
@@ -71,6 +72,7 @@ export function VideoFeed({}: NativeStackScreenProps<
'VideoFeed'
>) {
const {top} = useSafeAreaInsets()
const {params} = useRoute<RouteProp<CommonNavigatorParams, 'VideoFeed'>>()
const setMinShellMode = useSetMinimalShellMode()
useFocusEffect(
@@ -93,16 +95,7 @@ export function VideoFeed({}: NativeStackScreenProps<
a.z_30,
{top: 0, left: 0, right: 0, paddingTop: top},
]}>
<Layout.Header.Outer noBottomBorder>
<Layout.Header.BackButton />
<Layout.Header.Content>
<Layout.Header.TitleText>
{/* TODO: needs to be feed name */}
<Trans>Videos</Trans>
</Layout.Header.TitleText>
</Layout.Header.Content>
<Layout.Header.Slot />
</Layout.Header.Outer>
<Header sourceContext={params} />
</View>
<Inner />
</Layout.Screen>
+126
View File
@@ -0,0 +1,126 @@
import {View} from 'react-native'
import {sanitizeHandle} from '#/lib/strings/handles'
import {useFeedSourceInfoQuery} from '#/state/queries/feed'
import {UserAvatar} from '#/view/com/util/UserAvatar'
import {VideoFeedSourceContext} from '#/screens/VideoFeed/types'
import {atoms as a, useBreakpoints} from '#/alf'
import * as Layout from '#/components/Layout'
import {Text} from '#/components/Typography'
export function HeaderPlaceholder() {
return (
<View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}>
<View
style={[
a.rounded_sm,
{
width: 36,
height: 36,
backgroundColor: 'white',
opacity: 0.8,
},
]}
/>
<View style={[a.flex_1, a.gap_xs]}>
<View
style={[
a.w_full,
a.rounded_xs,
{
backgroundColor: 'white',
height: 14,
width: 80,
opacity: 0.8,
},
]}
/>
<View
style={[
a.w_full,
a.rounded_xs,
{
backgroundColor: 'white',
height: 10,
width: 140,
opacity: 0.6,
},
]}
/>
</View>
</View>
)
}
export function Header({
sourceContext,
}: {
sourceContext: VideoFeedSourceContext
}) {
let content = null
switch (sourceContext.type) {
case 'feedgen': {
content = <FeedHeader sourceContext={sourceContext} />
break
}
case 'author':
// TODO
default: {
break
}
}
return (
<Layout.Header.Outer noBottomBorder>
<Layout.Header.BackButton />
<Layout.Header.Content align="left">{content}</Layout.Header.Content>
</Layout.Header.Outer>
)
}
export function FeedHeader({
sourceContext,
}: {
sourceContext: Exclude<VideoFeedSourceContext, {type: 'author'}>
}) {
const {gtMobile} = useBreakpoints()
const {
data: info,
isLoading,
error,
} = useFeedSourceInfoQuery({uri: sourceContext.uri})
if (isLoading) {
return <HeaderPlaceholder />
} else if (error || !info) {
return null
}
return (
<View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}>
{info.avatar && <UserAvatar size={36} type="algo" avatar={info.avatar} />}
<View style={[a.flex_1]}>
<Text
style={[
a.text_md,
a.font_heavy,
a.leading_tight,
gtMobile && a.text_lg,
]}
numberOfLines={2}>
{info.displayName}
</Text>
<View style={[a.flex_row, {gap: 6}]}>
<Text
style={[a.flex_shrink, a.text_sm, a.leading_snug]}
numberOfLines={1}>
{sanitizeHandle(info.creatorHandle, '@')}
</Text>
</View>
</View>
</View>
)
}
+13
View File
@@ -0,0 +1,13 @@
import {AuthorFilter} from '#/state/queries/post-feed'
/**
* Kind of like `FeedDescriptor` but not
*/
export type VideoFeedSourceContext =
| {type: 'feedgen'; uri: string; initialPostUri?: string}
| {
type: 'author'
did: string
filter: AuthorFilter
initialPostUri?: string
}