diff options
Diffstat (limited to 'src/view/com/notifications')
-rw-r--r-- | src/view/com/notifications/FeedItem.tsx | 35 | ||||
-rw-r--r-- | src/view/com/notifications/InviteAccepter.tsx | 96 |
2 files changed, 126 insertions, 5 deletions
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index c67e6b966..fdc893e78 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -1,6 +1,6 @@ import React, {useMemo} from 'react' import {observer} from 'mobx-react-lite' -import {Image, StyleSheet, Text, View} from 'react-native' +import {StyleSheet, Text, View} from 'react-native' import {AtUri} from '../../../third-party/uri' import {FontAwesomeIcon, Props} from '@fortawesome/react-native-fontawesome' import {NotificationsViewItemModel} from '../../../state/models/notifications-view' @@ -11,6 +11,7 @@ import {UserAvatar} from '../util/UserAvatar' import {PostText} from '../post/PostText' import {Post} from '../post/Post' import {Link} from '../util/Link' +import {InviteAccepter} from './InviteAccepter' const MAX_AUTHORS = 8 @@ -20,10 +21,10 @@ export const FeedItem = observer(function FeedItem({ item: NotificationsViewItemModel }) { const itemHref = useMemo(() => { - if (item.isUpvote || item.isRepost) { + if (item.isUpvote || item.isRepost || item.isTrend) { const urip = new AtUri(item.subjectUri) return `/profile/${urip.host}/post/${urip.rkey}` - } else if (item.isFollow) { + } else if (item.isFollow || item.isAssertion) { return `/profile/${item.author.handle}` } else if (item.isReply) { const urip = new AtUri(item.uri) @@ -34,7 +35,7 @@ export const FeedItem = observer(function FeedItem({ const itemTitle = useMemo(() => { if (item.isUpvote || item.isRepost) { return 'Post' - } else if (item.isFollow) { + } else if (item.isFollow || item.isAssertion) { return item.author.handle } else if (item.isReply) { return 'Post' @@ -66,6 +67,10 @@ export const FeedItem = observer(function FeedItem({ action = 'reposted your post' icon = 'retweet' iconStyle = [s.green3] + } else if (item.isTrend) { + action = 'Your post is trending with' + icon = 'arrow-trend-up' + iconStyle = [s.blue3] } else if (item.isReply) { action = 'replied to your post' icon = ['far', 'comment'] @@ -73,6 +78,10 @@ export const FeedItem = observer(function FeedItem({ action = 'followed you' icon = 'user-plus' iconStyle = [s.blue3] + } else if (item.isInvite) { + icon = 'users' + iconStyle = [s.blue3] + action = 'invited you to join their scene' } else { return <></> } @@ -133,6 +142,9 @@ export const FeedItem = observer(function FeedItem({ ) : undefined} </View> <View style={styles.meta}> + {item.isTrend && ( + <Text style={[styles.metaItem, s.f15]}>{action}</Text> + )} <Link key={authors[0].href} style={styles.metaItem} @@ -150,7 +162,9 @@ export const FeedItem = observer(function FeedItem({ </Text> </> ) : undefined} - <Text style={[styles.metaItem, s.f15]}>{action}</Text> + {!item.isTrend && ( + <Text style={[styles.metaItem, s.f15]}>{action}</Text> + )} <Text style={[styles.metaItem, s.f15, s.gray5]}> {ago(item.indexedAt)} </Text> @@ -162,6 +176,11 @@ export const FeedItem = observer(function FeedItem({ )} </View> </View> + {item.isInvite && ( + <View style={styles.addedContainer}> + <InviteAccepter item={item} /> + </View> + )} {item.isReply ? ( <View style={s.pt5}> <Post uri={item.uri} /> @@ -216,6 +235,7 @@ const styles = StyleSheet.create({ }, meta: { flexDirection: 'row', + flexWrap: 'wrap', paddingTop: 6, paddingBottom: 2, }, @@ -225,4 +245,9 @@ const styles = StyleSheet.create({ postText: { paddingBottom: 5, }, + + addedContainer: { + paddingTop: 4, + paddingLeft: 36, + }, }) diff --git a/src/view/com/notifications/InviteAccepter.tsx b/src/view/com/notifications/InviteAccepter.tsx new file mode 100644 index 000000000..7d735a66b --- /dev/null +++ b/src/view/com/notifications/InviteAccepter.tsx @@ -0,0 +1,96 @@ +import React, {useState} from 'react' +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' +import LinearGradient from 'react-native-linear-gradient' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import * as apilib from '../../../state/lib/api' +import {NotificationsViewItemModel} from '../../../state/models/notifications-view' +import {ConfirmModel} from '../../../state/models/shell-ui' +import {useStores} from '../../../state' +import {ProfileCard} from '../profile/ProfileCard' +import Toast from '../util/Toast' +import {s, colors, gradients} from '../../lib/styles' + +export function InviteAccepter({item}: {item: NotificationsViewItemModel}) { + const store = useStores() + const [confirmationUri, setConfirmationUri] = useState<string>('') + const isMember = + confirmationUri !== '' || store.me.memberships?.isMemberOf(item.author.did) + const onPressAccept = async () => { + store.shell.openModal( + new ConfirmModel( + 'Join this scene?', + () => ( + <View> + <View style={styles.profileCardContainer}> + <ProfileCard + did={item.author.did} + handle={item.author.handle} + displayName={item.author.displayName} + /> + </View> + </View> + ), + onPressConfirmAccept, + ), + ) + } + const onPressConfirmAccept = async () => { + const uri = await apilib.acceptSceneInvite(store, { + originator: { + did: item.author.did, + declarationCid: item.author.declaration.cid, + }, + assertion: { + uri: item.uri, + cid: item.cid, + }, + }) + store.me.refreshMemberships() + Toast.show('Invite accepted', { + duration: Toast.durations.LONG, + position: Toast.positions.TOP, + }) + setConfirmationUri(uri) + } + return ( + <View style={styles.container}> + {!isMember ? ( + <TouchableOpacity onPress={onPressAccept}> + <LinearGradient + colors={[gradients.primary.start, gradients.primary.end]} + start={{x: 0, y: 0}} + end={{x: 1, y: 1}} + style={[styles.btn]}> + <Text style={[s.white, s.bold, s.f16]}>Accept Invite</Text> + </LinearGradient> + </TouchableOpacity> + ) : ( + <View style={styles.inviteAccepted}> + <FontAwesomeIcon icon="check" size={14} style={s.mr5} /> + <Text style={[s.gray5, s.f15]}>Invite accepted</Text> + </View> + )} + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + }, + btn: { + borderRadius: 32, + paddingHorizontal: 18, + paddingVertical: 8, + backgroundColor: colors.gray1, + }, + profileCardContainer: { + borderWidth: 1, + borderColor: colors.gray3, + borderRadius: 6, + }, + inviteAccepted: { + flexDirection: 'row', + alignItems: 'center', + }, +}) |