More fixes to mobile onboard

zio/stable
Paul Frazee 2023-08-30 15:15:10 -07:00
parent 05d1d8d8a4
commit 8ed6e72ea4
8 changed files with 255 additions and 166 deletions

View File

@ -1,8 +1,14 @@
import {useMediaQuery} from 'react-responsive'
import {isNative} from 'platform/detection'
export function useWebMediaQueries() {
const isDesktop = useMediaQuery({
query: '(min-width: 1230px)',
query: '(min-width: 1224px)',
})
return {isDesktop}
const isTabletOrMobile = useMediaQuery({query: '(max-width: 1224px)'})
const isMobile = useMediaQuery({query: '(max-width: 800px)'})
if (isNative) {
return {isMobile: true, isTabletOrMobile: true, isDesktop: false}
}
return {isMobile, isTabletOrMobile, isDesktop}
}

View File

@ -1,10 +1,11 @@
import 'react'
import {withBreakpoints} from 'view/com/util/layouts/withBreakpoints'
import {RecommendedFeedsDesktop} from './RecommendedFeedsDesktop'
import {RecommendedFeedsTablet} from './RecommendedFeedsTablet'
import {RecommendedFeedsMobile} from './RecommendedFeedsMobile'
export const RecommendedFeeds = withBreakpoints(
RecommendedFeedsMobile,
RecommendedFeedsMobile,
RecommendedFeedsTablet,
RecommendedFeedsDesktop,
)

View File

@ -4,14 +4,9 @@ import {observer} from 'mobx-react-lite'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {Text} from 'view/com/util/text/Text'
import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout'
import {UserAvatar} from 'view/com/util/UserAvatar'
import {Button} from 'view/com/util/forms/Button'
import * as Toast from 'view/com/util/Toast'
import {RecommendedFeedsItem} from './RecommendedFeedsItem'
import {usePalette} from 'lib/hooks/usePalette'
import {useCustomFeed} from 'lib/hooks/useCustomFeed'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {sanitizeHandle} from 'lib/strings/handles'
import {HeartIcon} from 'lib/icons'
import {RECOMMENDED_FEEDS} from 'lib/constants'
type Props = {
@ -64,7 +59,7 @@ export const RecommendedFeedsDesktop = observer(({next}: Props) => {
contentStyle={{paddingHorizontal: 0}}>
<FlatList
data={RECOMMENDED_FEEDS}
renderItem={({item}) => <Item {...item} />}
renderItem={({item}) => <RecommendedFeedsItem {...item} />}
keyExtractor={item => item.did + item.rkey}
style={{flex: 1}}
/>
@ -72,123 +67,6 @@ export const RecommendedFeedsDesktop = observer(({next}: Props) => {
)
})
const Item = observer(({did, rkey}: {did: string; rkey: string}) => {
const pal = usePalette('default')
const uri = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
const item = useCustomFeed(uri)
if (!item) return null
const onToggle = async () => {
if (item.isSaved) {
try {
await item.unsave()
} catch (e) {
Toast.show('There was an issue contacting your server')
console.error('Failed to unsave feed', {e})
}
} else {
try {
await item.save()
await item.pin()
} catch (e) {
Toast.show('There was an issue contacting your server')
console.error('Failed to pin feed', {e})
}
}
}
return (
<View testID={`feed-${item.displayName}`}>
<View
style={[
pal.border,
{
flexDirection: 'row',
gap: 18,
maxWidth: 670,
borderRightWidth: 1,
paddingHorizontal: 24,
paddingVertical: 24,
borderTopWidth: 1,
},
]}>
<View style={{marginTop: 2}}>
<UserAvatar type="algo" size={42} avatar={item.data.avatar} />
</View>
<View>
<Text
type="2xl-bold"
numberOfLines={1}
style={[pal.text, {fontSize: 19}]}>
{item.displayName}
</Text>
<Text style={[pal.textLight, {marginBottom: 8}]} numberOfLines={1}>
by {sanitizeHandle(item.data.creator.handle, '@')}
</Text>
{item.data.description ? (
<Text
type="xl"
style={[pal.text, {maxWidth: 550, marginBottom: 18}]}
numberOfLines={6}>
{item.data.description}
</Text>
) : null}
<View style={{flexDirection: 'row', alignItems: 'center', gap: 12}}>
<Button
type="inverted"
style={{paddingVertical: 6}}
onPress={onToggle}>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
paddingRight: 2,
gap: 6,
}}>
{item.isSaved ? (
<>
<FontAwesomeIcon
icon="check"
size={16}
color={pal.colors.textInverted}
/>
<Text type="lg-medium" style={pal.textInverted}>
Added
</Text>
</>
) : (
<>
<FontAwesomeIcon
icon="plus"
size={16}
color={pal.colors.textInverted}
/>
<Text type="lg-medium" style={pal.textInverted}>
Add
</Text>
</>
)}
</View>
</Button>
<View style={{flexDirection: 'row', gap: 4}}>
<HeartIcon
size={16}
strokeWidth={2.5}
style={[pal.textLight, {position: 'relative', top: 2}]}
/>
<Text type="lg-medium" style={[pal.text, pal.textLight]}>
{item.data.likeCount || 0}
</Text>
</View>
</View>
</View>
</View>
</View>
)
})
const styles = StyleSheet.create({
container: {
flex: 1,

View File

@ -0,0 +1,142 @@
import React from 'react'
import {View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {Text} from 'view/com/util/text/Text'
import {Button} from 'view/com/util/forms/Button'
import {UserAvatar} from 'view/com/util/UserAvatar'
import * as Toast from 'view/com/util/Toast'
import {HeartIcon} from 'lib/icons'
import {usePalette} from 'lib/hooks/usePalette'
import {useCustomFeed} from 'lib/hooks/useCustomFeed'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {sanitizeHandle} from 'lib/strings/handles'
export const RecommendedFeedsItem = observer(
({did, rkey}: {did: string; rkey: string}) => {
const {isMobile} = useWebMediaQueries()
const pal = usePalette('default')
const uri = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
const item = useCustomFeed(uri)
if (!item) return null
const onToggle = async () => {
if (item.isSaved) {
try {
await item.unsave()
} catch (e) {
Toast.show('There was an issue contacting your server')
console.error('Failed to unsave feed', {e})
}
} else {
try {
await item.save()
await item.pin()
} catch (e) {
Toast.show('There was an issue contacting your server')
console.error('Failed to pin feed', {e})
}
}
}
return (
<View testID={`feed-${item.displayName}`}>
<View
style={[
pal.border,
{
flex: isMobile ? 1 : undefined,
flexDirection: 'row',
gap: 18,
maxWidth: isMobile ? undefined : 670,
borderRightWidth: isMobile ? undefined : 1,
paddingHorizontal: 24,
paddingVertical: isMobile ? 12 : 24,
borderTopWidth: 1,
},
]}>
<View style={{marginTop: 2}}>
<UserAvatar type="algo" size={42} avatar={item.data.avatar} />
</View>
<View style={{flex: isMobile ? 1 : undefined}}>
<Text
type="2xl-bold"
numberOfLines={1}
style={[pal.text, {fontSize: 19}]}>
{item.displayName}
</Text>
<Text style={[pal.textLight, {marginBottom: 8}]} numberOfLines={1}>
by {sanitizeHandle(item.data.creator.handle, '@')}
</Text>
{item.data.description ? (
<Text
type="xl"
style={[
pal.text,
{
flex: isMobile ? 1 : undefined,
maxWidth: 550,
marginBottom: 18,
},
]}
numberOfLines={6}>
{item.data.description}
</Text>
) : null}
<View style={{flexDirection: 'row', alignItems: 'center', gap: 12}}>
<Button
type="inverted"
style={{paddingVertical: 6}}
onPress={onToggle}>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
paddingRight: 2,
gap: 6,
}}>
{item.isSaved ? (
<>
<FontAwesomeIcon
icon="check"
size={16}
color={pal.colors.textInverted}
/>
<Text type="lg-medium" style={pal.textInverted}>
Added
</Text>
</>
) : (
<>
<FontAwesomeIcon
icon="plus"
size={16}
color={pal.colors.textInverted}
/>
<Text type="lg-medium" style={pal.textInverted}>
Add
</Text>
</>
)}
</View>
</Button>
<View style={{flexDirection: 'row', gap: 4}}>
<HeartIcon
size={16}
strokeWidth={2.5}
style={[pal.textLight, {position: 'relative', top: 2}]}
/>
<Text type="lg-medium" style={[pal.text, pal.textLight]}>
{item.data.likeCount || 0}
</Text>
</View>
</View>
</View>
</View>
</View>
)
},
)

View File

@ -1,14 +1,11 @@
import React from 'react'
import {FlatList, StyleSheet, View} from 'react-native'
import {Text} from 'view/com/util/text/Text'
import {usePalette} from 'lib/hooks/usePalette'
import {Button} from 'view/com/util/forms/Button'
import {observer} from 'mobx-react-lite'
import {CustomFeed} from 'view/com/feeds/CustomFeed'
import {useCustomFeed} from 'lib/hooks/useCustomFeed'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {Text} from 'view/com/util/text/Text'
import {Button} from 'view/com/util/forms/Button'
import {ViewHeader} from 'view/com/util/ViewHeader'
import {isDesktopWeb} from 'platform/detection'
import {RecommendedFeedsItem} from './RecommendedFeedsItem'
import {usePalette} from 'lib/hooks/usePalette'
import {RECOMMENDED_FEEDS} from 'lib/constants'
type Props = {
@ -31,7 +28,7 @@ export const RecommendedFeedsMobile = observer(({next}: Props) => {
<FlatList
data={RECOMMENDED_FEEDS}
renderItem={({item}) => <Item item={item} />}
renderItem={({item}) => <RecommendedFeedsItem {...item} />}
keyExtractor={item => item.did + item.rkey}
style={{flex: 1}}
/>
@ -47,32 +44,6 @@ export const RecommendedFeedsMobile = observer(({next}: Props) => {
)
})
type ItemProps = {
did: string
rkey: string
}
const Item = ({item}: {item: ItemProps}) => {
const uri = makeRecordUri(item.did, 'app.bsky.feed.generator', item.rkey)
const data = useCustomFeed(uri)
if (!data) return null
return (
<CustomFeed
item={data}
key={uri}
showDescription
showLikes
showSaveBtn
style={[
{
// @ts-ignore
cursor: isDesktopWeb ? 'pointer' : 'auto',
},
]}
/>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
@ -83,7 +54,7 @@ const styles = StyleSheet.create({
marginHorizontal: 16,
},
button: {
marginBottom: 24,
marginBottom: 16,
marginHorizontal: 16,
marginTop: 16,
},

View File

@ -0,0 +1,91 @@
import React from 'react'
import {FlatList, StyleSheet, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {Text} from 'view/com/util/text/Text'
import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout'
import {Button} from 'view/com/util/forms/Button'
import {RecommendedFeedsItem} from './RecommendedFeedsItem'
import {usePalette} from 'lib/hooks/usePalette'
import {RECOMMENDED_FEEDS} from 'lib/constants'
type Props = {
next: () => void
}
export const RecommendedFeedsTablet = observer(({next}: Props) => {
const pal = usePalette('default')
const title = (
<>
<Text style={[pal.textLight, styles.title1]}>Choose your</Text>
<Text style={[pal.link, styles.title2]}>Recomended</Text>
<Text style={[pal.link, styles.title2]}>Feeds</Text>
<Text type="2xl-medium" style={[pal.textLight, styles.description]}>
Feeds are created by users to curate content. Choose some feeds that you
find interesting.
</Text>
<View
style={{
flexDirection: 'row',
justifyContent: 'flex-end',
marginTop: 20,
}}>
<Button onPress={next} testID="continueBtn">
<View
style={{
flexDirection: 'row',
alignItems: 'center',
paddingLeft: 2,
gap: 6,
}}>
<Text
type="2xl-medium"
style={{color: '#fff', position: 'relative', top: -1}}>
Done
</Text>
<FontAwesomeIcon icon="angle-right" color="#fff" size={14} />
</View>
</Button>
</View>
</>
)
return (
<TitleColumnLayout
testID="recommendedFeedsScreen"
title={title}
horizontal
contentStyle={{paddingHorizontal: 0}}>
<FlatList
data={RECOMMENDED_FEEDS}
renderItem={({item}) => <RecommendedFeedsItem {...item} />}
keyExtractor={item => item.did + item.rkey}
style={{flex: 1}}
/>
</TitleColumnLayout>
)
})
const styles = StyleSheet.create({
container: {
flex: 1,
marginHorizontal: 16,
justifyContent: 'space-between',
},
title1: {
fontSize: 24,
fontWeight: '800',
textAlign: 'right',
},
title2: {
fontSize: 36,
fontWeight: '800',
textAlign: 'right',
},
description: {
maxWidth: 400,
marginTop: 10,
marginLeft: 'auto',
textAlign: 'right',
},
})

View File

@ -1,6 +1,6 @@
import React from 'react'
import {useMediaQuery} from 'react-responsive'
import {isNative} from 'platform/detection'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
export const withBreakpoints =
<P extends object>(
@ -9,8 +9,7 @@ export const withBreakpoints =
Desktop: React.ComponentType<P>,
): React.FC<P> =>
(props: P) => {
const isTabletOrMobile = useMediaQuery({query: '(max-width: 1224px)'})
const isMobile = useMediaQuery({query: '(max-width: 800px)'})
const {isMobile, isTabletOrMobile} = useWebMediaQueries()
if (isMobile || isNative) {
return <Mobile {...props} />

View File

@ -28,6 +28,7 @@ const ShellInner = observer(() => {
})
}, [navigator, store.shell])
const showBottomBar = !isDesktop && !store.onboarding.isActive
const showSideNavs =
isDesktop && store.session.hasSession && !store.onboarding.isActive
return (
@ -52,7 +53,7 @@ const ShellInner = observer(() => {
onPost={store.shell.composerOpts?.onPost}
mention={store.shell.composerOpts?.mention}
/>
{!isDesktop && <BottomBarWeb />}
{showBottomBar && <BottomBarWeb />}
<ModalsContainer />
<Lightbox />
{!isDesktop && store.shell.isDrawerOpen && (