diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/notifications/FeedItem.tsx | 33 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 68 | ||||
-rw-r--r-- | src/view/com/post-thread/PostVotedBy.tsx (renamed from src/view/com/post-thread/PostLikedBy.tsx) | 42 | ||||
-rw-r--r-- | src/view/com/post/Post.tsx | 20 | ||||
-rw-r--r-- | src/view/com/posts/FeedItem.tsx | 20 | ||||
-rw-r--r-- | src/view/com/util/PostCtrls.tsx | 30 | ||||
-rw-r--r-- | src/view/com/util/UserInfoText.tsx | 2 | ||||
-rw-r--r-- | src/view/routes.ts | 12 | ||||
-rw-r--r-- | src/view/screens/PostDownvotedBy.tsx | 26 | ||||
-rw-r--r-- | src/view/screens/PostUpvotedBy.tsx (renamed from src/view/screens/PostLikedBy.tsx) | 10 |
10 files changed, 181 insertions, 82 deletions
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index 45bad95fc..c67e6b966 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -6,6 +6,7 @@ import {FontAwesomeIcon, Props} from '@fortawesome/react-native-fontawesome' import {NotificationsViewItemModel} from '../../../state/models/notifications-view' import {s, colors} from '../../lib/styles' import {ago, pluralize} from '../../lib/strings' +import {UpIconSolid} from '../../lib/icons' import {UserAvatar} from '../util/UserAvatar' import {PostText} from '../post/PostText' import {Post} from '../post/Post' @@ -19,7 +20,7 @@ export const FeedItem = observer(function FeedItem({ item: NotificationsViewItemModel }) { const itemHref = useMemo(() => { - if (item.isLike || item.isRepost) { + if (item.isUpvote || item.isRepost) { const urip = new AtUri(item.subjectUri) return `/profile/${urip.host}/post/${urip.rkey}` } else if (item.isFollow) { @@ -31,7 +32,7 @@ export const FeedItem = observer(function FeedItem({ return '' }, [item]) const itemTitle = useMemo(() => { - if (item.isLike || item.isRepost) { + if (item.isUpvote || item.isRepost) { return 'Post' } else if (item.isFollow) { return item.author.handle @@ -55,16 +56,16 @@ export const FeedItem = observer(function FeedItem({ } let action = '' - let icon: Props['icon'] + let icon: Props['icon'] | 'UpIconSolid' let iconStyle: Props['style'] = [] - if (item.isLike) { - action = 'liked your post' - icon = ['fas', 'heart'] - iconStyle = [s.blue3] + if (item.isUpvote) { + action = 'upvoted your post' + icon = 'UpIconSolid' + iconStyle = [s.red3, {position: 'relative', top: -4}] } else if (item.isRepost) { action = 'reposted your post' icon = 'retweet' - iconStyle = [s.blue3] + iconStyle = [s.green3] } else if (item.isReply) { action = 'replied to your post' icon = ['far', 'comment'] @@ -100,11 +101,15 @@ export const FeedItem = observer(function FeedItem({ title={itemTitle}> <View style={styles.layout}> <View style={styles.layoutIcon}> - <FontAwesomeIcon - icon={icon} - size={22} - style={[styles.icon, ...iconStyle]} - /> + {icon === 'UpIconSolid' ? ( + <UpIconSolid size={26} style={[styles.icon, ...iconStyle]} /> + ) : ( + <FontAwesomeIcon + icon={icon} + size={22} + style={[styles.icon, ...iconStyle]} + /> + )} </View> <View style={styles.layoutContent}> <View style={styles.avis}> @@ -150,7 +155,7 @@ export const FeedItem = observer(function FeedItem({ {ago(item.indexedAt)} </Text> </View> - {item.isLike || item.isRepost ? ( + {item.isUpvote || item.isRepost ? ( <PostText uri={item.subjectUri} style={[s.gray5]} /> ) : ( <></> diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 17f37cb2e..a4b628101 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -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 + .toggleUpvote() + .catch(e => console.error('Failed to toggle upvote', record, e)) + } + const onPressToggleDownvote = () => { item - .toggleLike() - .catch(e => console.error('Failed to toggle like', record, e)) + .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={upvotesHref} + title={upvotesTitle}> + <Text style={[s.gray5, s.semiBold, s.f16]}> + <Text style={[s.bold, s.black, s.f16]}> + {item.upvoteCount} + </Text>{' '} + {pluralize(item.upvoteCount, 'upvote')} + </Text> + </Link> + ) : ( + <></> + )} + {item.downvoteCount ? ( <Link style={styles.expandedInfoItem} - href={likesHref} - title={likesTitle}> + href={downvotesHref} + title={downvotesTitle}> <Text style={[s.gray5, s.semiBold, s.f16]}> <Text style={[s.bold, s.black, s.f16]}> - {item.likeCount} + {item.downvoteCount} </Text>{' '} - {pluralize(item.likeCount, 'like')} + {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> diff --git a/src/view/com/post-thread/PostLikedBy.tsx b/src/view/com/post-thread/PostVotedBy.tsx index 87829955e..f5b01f0db 100644 --- a/src/view/com/post-thread/PostLikedBy.tsx +++ b/src/view/com/post-thread/PostVotedBy.tsx @@ -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> diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index 37d25a7b1..4a1e67b63 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -78,10 +78,15 @@ export const Post = observer(function Post({uri}: {uri: string}) { .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)) } return ( @@ -129,12 +134,15 @@ export const Post = observer(function Post({uri}: {uri: string}) { <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> diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index feaa78550..73593166c 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -48,10 +48,15 @@ export const FeedItem = observer(function FeedItem({ .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)) } const onPressShare = (uri: string) => { store.shell.openModal(new SharePostModel(uri)) @@ -129,12 +134,15 @@ export const FeedItem = observer(function FeedItem({ <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> diff --git a/src/view/com/util/PostCtrls.tsx b/src/view/com/util/PostCtrls.tsx index 3dd77eb30..707030ea2 100644 --- a/src/view/com/util/PostCtrls.tsx +++ b/src/view/com/util/PostCtrls.tsx @@ -7,12 +7,15 @@ import {s, colors} from '../../lib/styles' interface PostCtrlsOpts { replyCount: number repostCount: number - likeCount: number + upvoteCount: number + downvoteCount: number isReposted: boolean - isLiked: boolean + isUpvoted: boolean + isDownvoted: boolean onPressReply: () => void onPressToggleRepost: () => void - onPressToggleLike: () => void + onPressToggleUpvote: () => void + onPressToggleDownvote: () => void } export function PostCtrls(opts: PostCtrlsOpts) { @@ -36,22 +39,27 @@ export function PostCtrls(opts: PostCtrlsOpts) { {opts.repostCount} </Text> </TouchableOpacity> - <TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleLike}> - {opts.isLiked ? ( + <TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleUpvote}> + {opts.isUpvoted ? ( <UpIconSolid style={styles.ctrlIconUpvoted} size={18} /> ) : ( <UpIcon style={styles.ctrlIcon} size={18} /> )} - <Text style={opts.isLiked ? [s.bold, s.blue3, s.f13] : s.f13}> - {opts.likeCount} + <Text style={opts.isUpvoted ? [s.bold, s.red3, s.f13] : s.f13}> + {opts.upvoteCount} </Text> </TouchableOpacity> - <TouchableOpacity style={styles.ctrl} onPress={opts.onPressToggleLike}> - {opts.isLiked ? ( + <TouchableOpacity + style={styles.ctrl} + onPress={opts.onPressToggleDownvote}> + {opts.isDownvoted ? ( <DownIconSolid style={styles.ctrlIconDownvoted} size={18} /> ) : ( <DownIcon style={styles.ctrlIcon} size={18} /> )} + <Text style={opts.isDownvoted ? [s.bold, s.blue3, s.f13] : s.f13}> + {opts.downvoteCount} + </Text> </TouchableOpacity> </View> ) @@ -78,10 +86,10 @@ const styles = StyleSheet.create({ }, ctrlIconUpvoted: { marginRight: 5, - color: colors.blue3, + color: colors.red3, }, ctrlIconDownvoted: { marginRight: 5, - color: colors.red3, + color: colors.blue3, }, }) diff --git a/src/view/com/util/UserInfoText.tsx b/src/view/com/util/UserInfoText.tsx index 411891863..77fb59886 100644 --- a/src/view/com/util/UserInfoText.tsx +++ b/src/view/com/util/UserInfoText.tsx @@ -31,7 +31,7 @@ export function UserInfoText({ useEffect(() => { let aborted = false // TODO use caching to reduce loads - store.api.app.bsky.actor.getProfile({user: did}).then( + store.api.app.bsky.actor.getProfile({actor: did}).then( v => { if (aborted) return setProfile(v.data) diff --git a/src/view/routes.ts b/src/view/routes.ts index d458813ec..a72afe592 100644 --- a/src/view/routes.ts +++ b/src/view/routes.ts @@ -7,7 +7,8 @@ import {Search} from './screens/Search' import {Notifications} from './screens/Notifications' import {NotFound} from './screens/NotFound' import {PostThread} from './screens/PostThread' -import {PostLikedBy} from './screens/PostLikedBy' +import {PostUpvotedBy} from './screens/PostUpvotedBy' +import {PostDownvotedBy} from './screens/PostDownvotedBy' import {PostRepostedBy} from './screens/PostRepostedBy' import {Profile} from './screens/Profile' import {ProfileFollowers} from './screens/ProfileFollowers' @@ -42,9 +43,14 @@ export const routes: Route[] = [ r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)'), ], [ - PostLikedBy, + PostUpvotedBy, 'heart', - r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)/liked-by'), + r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)/upvoted-by'), + ], + [ + PostDownvotedBy, + 'heart', + r('/profile/(?<name>[^/]+)/post/(?<rkey>[^/]+)/downvoted-by'), ], [ PostRepostedBy, diff --git a/src/view/screens/PostDownvotedBy.tsx b/src/view/screens/PostDownvotedBy.tsx new file mode 100644 index 000000000..a77476834 --- /dev/null +++ b/src/view/screens/PostDownvotedBy.tsx @@ -0,0 +1,26 @@ +import React, {useEffect} from 'react' +import {View} from 'react-native' +import {ViewHeader} from '../com/util/ViewHeader' +import {PostVotedBy as PostLikedByComponent} from '../com/post-thread/PostVotedBy' +import {ScreenParams} from '../routes' +import {useStores} from '../../state' +import {makeRecordUri} from '../lib/strings' + +export const PostDownvotedBy = ({visible, params}: ScreenParams) => { + const store = useStores() + const {name, rkey} = params + const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) + + useEffect(() => { + if (visible) { + store.nav.setTitle('Downvoted by') + } + }, [store, visible]) + + return ( + <View> + <ViewHeader title="Downvoted by" /> + <PostLikedByComponent uri={uri} direction="down" /> + </View> + ) +} diff --git a/src/view/screens/PostLikedBy.tsx b/src/view/screens/PostUpvotedBy.tsx index 8adc58c89..0bf662def 100644 --- a/src/view/screens/PostLikedBy.tsx +++ b/src/view/screens/PostUpvotedBy.tsx @@ -1,26 +1,26 @@ import React, {useEffect} from 'react' import {View} from 'react-native' import {ViewHeader} from '../com/util/ViewHeader' -import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy' +import {PostVotedBy as PostLikedByComponent} from '../com/post-thread/PostVotedBy' import {ScreenParams} from '../routes' import {useStores} from '../../state' import {makeRecordUri} from '../lib/strings' -export const PostLikedBy = ({visible, params}: ScreenParams) => { +export const PostUpvotedBy = ({visible, params}: ScreenParams) => { const store = useStores() const {name, rkey} = params const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) useEffect(() => { if (visible) { - store.nav.setTitle('Liked by') + store.nav.setTitle('Upvoted by') } }, [store, visible]) return ( <View> - <ViewHeader title="Liked by" /> - <PostLikedByComponent uri={uri} /> + <ViewHeader title="Upvoted by" /> + <PostLikedByComponent uri={uri} direction="up" /> </View> ) } |