Add right column of web shell and tweak left column

zio/stable
Paul Frazee 2023-01-26 19:49:16 -06:00
parent c24d0254bc
commit f51ad28025
4 changed files with 246 additions and 30 deletions

View File

@ -0,0 +1,194 @@
import React, {useEffect, useState} from 'react'
import {
ActivityIndicator,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native'
import LinearGradient from 'react-native-linear-gradient'
import {observer} from 'mobx-react-lite'
import _omit from 'lodash.omit'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {Link} from '../util/Link'
import {Text} from '../util/text/Text'
import {UserAvatar} from '../util/UserAvatar'
import * as Toast from '../util/Toast'
import {useStores} from '../../../state'
import * as apilib from '../../../state/lib/api'
import {
SuggestedActorsViewModel,
SuggestedActor,
} from '../../../state/models/suggested-actors-view'
import {s, gradients} from '../../lib/styles'
import {usePalette} from '../../lib/hooks/usePalette'
export const LiteSuggestedFollows = observer(() => {
const store = useStores()
const [suggestions, setSuggestions] = useState<SuggestedActor[] | undefined>(
undefined,
)
const [follows, setFollows] = useState<Record<string, string>>({})
useEffect(() => {
const view = new SuggestedActorsViewModel(store)
view.loadMore().then(
() => {
setSuggestions(view.suggestions.slice().sort(randomize).slice(0, 3))
},
(err: any) => {
setSuggestions([])
store.log.error('Failed to fetch suggestions', err)
},
)
}, [store, store.log])
const onPressFollow = async (item: SuggestedActor) => {
try {
const res = await apilib.follow(store, item.did, item.declaration.cid)
setFollows({[item.did]: res.uri, ...follows})
} catch (e: any) {
store.log.error('Failed fo create follow', e)
Toast.show('An issue occurred, please try again.')
}
}
const onPressUnfollow = async (item: SuggestedActor) => {
try {
await apilib.unfollow(store, follows[item.did])
setFollows(_omit(follows, [item.did]))
} catch (e: any) {
store.log.error('Failed fo delete follow', e)
Toast.show('An issue occurred, please try again.')
}
}
return (
<View>
{!suggestions ? (
<View>
<ActivityIndicator />
</View>
) : (
<View>
{suggestions.map(item => (
<Link
key={item.did}
href={`/profile/${item.handle}`}
title={item.displayName || item.handle}>
<User
item={item}
follow={follows[item.did]}
onPressFollow={onPressFollow}
onPressUnfollow={onPressUnfollow}
/>
</Link>
))}
</View>
)}
</View>
)
})
const User = ({
item,
follow,
onPressFollow,
onPressUnfollow,
}: {
item: SuggestedActor
follow: string | undefined
onPressFollow: (item: SuggestedActor) => void
onPressUnfollow: (item: SuggestedActor) => void
}) => {
const pal = usePalette('default')
return (
<View style={[styles.actor]}>
<View style={styles.actorMeta}>
<View style={styles.actorAvi}>
<UserAvatar
size={40}
displayName={item.displayName}
handle={item.handle}
avatar={item.avatar}
/>
</View>
<View style={styles.actorContent}>
<Text type="lg-medium" style={pal.text} numberOfLines={1}>
{item.displayName || item.handle}
</Text>
<Text type="sm" style={pal.textLight} numberOfLines={1}>
@{item.handle}
</Text>
</View>
<View style={styles.actorBtn}>
{follow ? (
<TouchableOpacity onPress={() => onPressUnfollow(item)}>
<View style={[styles.btn, styles.secondaryBtn, pal.btn]}>
<Text type="button" style={pal.text}>
Unfollow
</Text>
</View>
</TouchableOpacity>
) : (
<TouchableOpacity onPress={() => onPressFollow(item)}>
<LinearGradient
colors={[gradients.blueLight.start, gradients.blueLight.end]}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}
style={[styles.btn, styles.gradientBtn]}>
<Text type="sm-medium" style={s.white}>
Follow
</Text>
</LinearGradient>
</TouchableOpacity>
)}
</View>
</View>
</View>
)
}
function randomize() {
return Math.random() > 0.5 ? 1 : -1
}
const styles = StyleSheet.create({
footer: {
height: 200,
paddingTop: 20,
},
actor: {},
actorMeta: {
flexDirection: 'row',
},
actorAvi: {
width: 50,
paddingTop: 10,
paddingBottom: 10,
},
actorContent: {
flex: 1,
paddingRight: 10,
paddingTop: 10,
},
actorBtn: {
paddingRight: 10,
paddingTop: 10,
},
gradientBtn: {
paddingHorizontal: 14,
paddingVertical: 6,
},
secondaryBtn: {
paddingHorizontal: 8,
},
btn: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 7,
borderRadius: 50,
marginLeft: 6,
},
})

View File

@ -1,10 +1,10 @@
import React from 'react'
import {observer} from 'mobx-react-lite'
import {View, StyleSheet, Text} from 'react-native'
import {View, StyleSheet} from 'react-native'
import {useStores} from '../../../state'
import {match, MatchResult} from '../../routes'
import {DesktopLeftColumn} from './left-column'
// import {DesktopRightColumn} from './right-column'
import {DesktopRightColumn} from './right-column'
import {Login} from '../../screens/Login'
import {ErrorBoundary} from '../../com/util/ErrorBoundary'
import {usePalette} from '../../lib/hooks/usePalette'
@ -35,6 +35,7 @@ export const WebShell: React.FC = observer(() => {
</View>
))}
<DesktopLeftColumn />
<DesktopRightColumn />
</View>
)
// TODO
@ -48,25 +49,6 @@ export const WebShell: React.FC = observer(() => {
// imagesOpen={store.shell.composerOpts?.imagesOpen}
// onPost={store.shell.composerOpts?.onPost}
// />
// return (
// <View style={styles.outerContainer}>
// {store.session.hasSession ? (
// <>
// <DesktopLeftColumn />
// <View style={styles.innerContainer}>
// <Text>Hello, world! (Logged in)</Text>
// {children}
// </View>
// <DesktopRightColumn />
// </>
// ) : (
// <View style={styles.innerContainer}>
// <Text>Hello, world! (Logged out)</Text>
// {children}
// </View>
// )}
// </View>
// )
})
/**

View File

@ -42,7 +42,9 @@ export const NavItem = observer(
</Text>
)}
</View>
<Text type={isCurrent ? 'xl-bold' : 'xl-medium'}>{label}</Text>
<Text type={isCurrent ? 'xl-bold' : 'xl'} style={styles.navItemLabel}>
{label}
</Text>
</Link>
</Pressable>
)
@ -86,10 +88,11 @@ export const DesktopLeftColumn = observer(() => {
const styles = StyleSheet.create({
container: {
position: 'absolute',
left: 'calc(50vw - 500px)',
width: '200px',
left: 'calc(50vw - 530px)',
width: '230px',
height: '100%',
borderRightWidth: 1,
paddingTop: 20,
},
navItem: {
padding: '1rem',
@ -109,7 +112,11 @@ const styles = StyleSheet.create({
backgroundColor: colors.red3,
color: colors.white,
fontSize: 12,
fontWeight: 'bold',
paddingHorizontal: 4,
borderRadius: 4,
borderRadius: 6,
},
navItemLabel: {
fontSize: 19,
},
})

View File

@ -1,10 +1,28 @@
import React from 'react'
import {Text, View, StyleSheet} from 'react-native'
import {View, StyleSheet} from 'react-native'
import {Link} from '../../com/util/Link'
import {Text} from '../../com/util/text/Text'
import {usePalette} from '../../lib/hooks/usePalette'
import {MagnifyingGlassIcon} from '../../lib/icons'
import {LiteSuggestedFollows} from '../../com/discover/LiteSuggestedFollows'
import {s} from '../../lib/styles'
export const DesktopRightColumn: React.FC = () => {
const pal = usePalette('default')
return (
<View style={styles.container}>
<Text>Right Column</Text>
<View style={[styles.container, pal.border]}>
<Link href="/search" style={[pal.btn, styles.searchContainer]}>
<View style={styles.searchIcon}>
<MagnifyingGlassIcon style={pal.textLight} />
</View>
<Text type="lg" style={pal.textLight}>
Search
</Text>
</Link>
<Text type="xl-bold" style={s.mb10}>
Suggested Follows
</Text>
<LiteSuggestedFollows />
</View>
)
}
@ -12,8 +30,23 @@ export const DesktopRightColumn: React.FC = () => {
const styles = StyleSheet.create({
container: {
position: 'absolute',
right: 'calc(50vw - 500px)',
width: '200px',
right: 'calc(50vw - 650px)',
width: '350px',
height: '100%',
borderLeftWidth: 1,
overscrollBehavior: 'auto',
paddingLeft: 30,
paddingTop: 10,
},
searchContainer: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 14,
paddingVertical: 10,
borderRadius: 20,
marginBottom: 20,
},
searchIcon: {
marginRight: 5,
},
})