Finish the upvote/downvote implementation

This commit is contained in:
Paul Frazee 2022-11-08 12:14:51 -06:00
parent e650d98924
commit 1fbc4cf1f2
32 changed files with 1207 additions and 587 deletions

View file

@ -28,7 +28,8 @@ export const PostThreadItem = observer(function PostThreadItem({
}) {
const store = useStores()
const record = item.record as unknown as PostType.Record
const hasEngagement = item.likeCount || item.repostCount
const hasEngagement =
item.upvoteCount || item.downvoteCount || item.repostCount
const itemHref = useMemo(() => {
const urip = new AtUri(item.uri)
@ -37,11 +38,16 @@ export const PostThreadItem = observer(function PostThreadItem({
const itemTitle = `Post by ${item.author.handle}`
const authorHref = `/profile/${item.author.handle}`
const authorTitle = item.author.handle
const likesHref = useMemo(() => {
const upvotesHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.handle}/post/${urip.rkey}/liked-by`
return `/profile/${item.author.handle}/post/${urip.rkey}/upvoted-by`
}, [item.uri, item.author.handle])
const likesTitle = 'Likes on this post'
const upvotesTitle = 'Upvotes on this post'
const downvotesHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.handle}/post/${urip.rkey}/downvoted-by`
}, [item.uri, item.author.handle])
const downvotesTitle = 'Downvotes on this post'
const repostsHref = useMemo(() => {
const urip = new AtUri(item.uri)
return `/profile/${item.author.handle}/post/${urip.rkey}/reposted-by`
@ -59,10 +65,15 @@ export const PostThreadItem = observer(function PostThreadItem({
.toggleRepost()
.catch(e => console.error('Failed to toggle repost', record, e))
}
const onPressToggleLike = () => {
const onPressToggleUpvote = () => {
item
.toggleLike()
.catch(e => console.error('Failed to toggle like', record, e))
.toggleUpvote()
.catch(e => console.error('Failed to toggle upvote', record, e))
}
const onPressToggleDownvote = () => {
item
.toggleDownvote()
.catch(e => console.error('Failed to toggle downvote', record, e))
}
if (item._isHighlightedPost) {
@ -135,16 +146,31 @@ export const PostThreadItem = observer(function PostThreadItem({
) : (
<></>
)}
{item.likeCount ? (
{item.upvoteCount ? (
<Link
style={styles.expandedInfoItem}
href={likesHref}
title={likesTitle}>
href={upvotesHref}
title={upvotesTitle}>
<Text style={[s.gray5, s.semiBold, s.f16]}>
<Text style={[s.bold, s.black, s.f16]}>
{item.likeCount}
{item.upvoteCount}
</Text>{' '}
{pluralize(item.likeCount, 'like')}
{pluralize(item.upvoteCount, 'upvote')}
</Text>
</Link>
) : (
<></>
)}
{item.downvoteCount ? (
<Link
style={styles.expandedInfoItem}
href={downvotesHref}
title={downvotesTitle}>
<Text style={[s.gray5, s.semiBold, s.f16]}>
<Text style={[s.bold, s.black, s.f16]}>
{item.downvoteCount}
</Text>{' '}
{pluralize(item.downvoteCount, 'downvote')}
</Text>
</Link>
) : (
@ -158,12 +184,15 @@ export const PostThreadItem = observer(function PostThreadItem({
<PostCtrls
replyCount={item.replyCount}
repostCount={item.repostCount}
likeCount={item.likeCount}
upvoteCount={item.upvoteCount}
downvoteCount={item.downvoteCount}
isReposted={!!item.myState.repost}
isLiked={!!item.myState.like}
isUpvoted={!!item.myState.upvote}
isDownvoted={!!item.myState.downvote}
onPressReply={onPressReply}
onPressToggleRepost={onPressToggleRepost}
onPressToggleLike={onPressToggleLike}
onPressToggleUpvote={onPressToggleUpvote}
onPressToggleDownvote={onPressToggleDownvote}
/>
</View>
</View>
@ -260,12 +289,15 @@ export const PostThreadItem = observer(function PostThreadItem({
<PostCtrls
replyCount={item.replyCount}
repostCount={item.repostCount}
likeCount={item.likeCount}
upvoteCount={item.upvoteCount}
downvoteCount={item.downvoteCount}
isReposted={!!item.myState.repost}
isLiked={!!item.myState.like}
isUpvoted={!!item.myState.upvote}
isDownvoted={!!item.myState.downvote}
onPressReply={onPressReply}
onPressToggleRepost={onPressToggleRepost}
onPressToggleLike={onPressToggleLike}
onPressToggleUpvote={onPressToggleUpvote}
onPressToggleDownvote={onPressToggleDownvote}
/>
</View>
</View>

View file

@ -2,27 +2,33 @@ import React, {useState, useEffect} from 'react'
import {observer} from 'mobx-react-lite'
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from 'react-native'
import {
LikedByViewModel,
LikedByViewItemModel,
} from '../../../state/models/liked-by-view'
VotesViewModel,
VotesViewItemModel,
} from '../../../state/models/votes-view'
import {Link} from '../util/Link'
import {UserAvatar} from '../util/UserAvatar'
import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles'
export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
export const PostVotedBy = observer(function PostVotedBy({
uri,
direction,
}: {
uri: string
direction: 'up' | 'down'
}) {
const store = useStores()
const [view, setView] = useState<LikedByViewModel | undefined>()
const [view, setView] = useState<VotesViewModel | undefined>()
useEffect(() => {
if (view?.params.uri === uri) {
console.log('Liked by doing nothing')
console.log('Voted by doing nothing')
return // no change needed? or trigger refresh?
}
console.log('Fetching Liked by', uri)
const newView = new LikedByViewModel(store, {uri})
console.log('Fetching voted by', uri)
const newView = new VotesViewModel(store, {uri, direction})
setView(newView)
newView.setup().catch(err => console.error('Failed to fetch liked by', err))
newView.setup().catch(err => console.error('Failed to fetch voted by', err))
}, [uri, view?.params.uri, store])
// loading
@ -51,13 +57,13 @@ export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
// loaded
// =
const renderItem = ({item}: {item: LikedByViewItemModel}) => (
const renderItem = ({item}: {item: VotesViewItemModel}) => (
<LikedByItem item={item} />
)
return (
<View>
<FlatList
data={view.likedBy}
data={view.votes}
keyExtractor={item => item._reactKey}
renderItem={renderItem}
/>
@ -65,23 +71,23 @@ export const PostLikedBy = observer(function PostLikedBy({uri}: {uri: string}) {
)
})
const LikedByItem = ({item}: {item: LikedByViewItemModel}) => {
const LikedByItem = ({item}: {item: VotesViewItemModel}) => {
return (
<Link
style={styles.outer}
href={`/profile/${item.handle}`}
title={item.handle}>
href={`/profile/${item.actor.handle}`}
title={item.actor.handle}>
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<UserAvatar
size={40}
displayName={item.displayName}
handle={item.handle}
displayName={item.actor.displayName}
handle={item.actor.handle}
/>
</View>
<View style={styles.layoutContent}>
<Text style={[s.f15, s.bold]}>{item.displayName}</Text>
<Text style={[s.f14, s.gray5]}>@{item.handle}</Text>
<Text style={[s.f15, s.bold]}>{item.actor.displayName}</Text>
<Text style={[s.f14, s.gray5]}>@{item.actor.handle}</Text>
</View>
</View>
</Link>