about summary refs log tree commit diff
path: root/src/view/com/notifications
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/notifications')
-rw-r--r--src/view/com/notifications/FeedItem.tsx35
-rw-r--r--src/view/com/notifications/InviteAccepter.tsx96
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',
+  },
+})