about summary refs log tree commit diff
path: root/src/view/com/posts/FeedErrorMessage.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/posts/FeedErrorMessage.tsx')
-rw-r--r--src/view/com/posts/FeedErrorMessage.tsx198
1 files changed, 157 insertions, 41 deletions
diff --git a/src/view/com/posts/FeedErrorMessage.tsx b/src/view/com/posts/FeedErrorMessage.tsx
index 9e75d9507..63d9d5956 100644
--- a/src/view/com/posts/FeedErrorMessage.tsx
+++ b/src/view/com/posts/FeedErrorMessage.tsx
@@ -1,7 +1,6 @@
 import React from 'react'
 import {View} from 'react-native'
-import {AtUri, AppBskyFeedGetFeed as GetCustomFeed} from '@atproto/api'
-import {PostsFeedModel, KnownError} from 'state/models/feeds/posts'
+import {AppBskyFeedGetAuthorFeed, AtUri} from '@atproto/api'
 import {Text} from '../util/text/Text'
 import {Button} from '../util/forms/Button'
 import * as Toast from '../util/Toast'
@@ -9,67 +8,118 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useNavigation} from '@react-navigation/native'
 import {NavigationProp} from 'lib/routes/types'
-import {useStores} from 'state/index'
 import {logger} from '#/logger'
+import {useModalControls} from '#/state/modals'
+import {msg as msgLingui} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {FeedDescriptor} from '#/state/queries/post-feed'
+import {EmptyState} from '../util/EmptyState'
+import {cleanError} from '#/lib/strings/errors'
+import {useRemoveFeedMutation} from '#/state/queries/preferences'
 
-const MESSAGES = {
-  [KnownError.Unknown]: '',
-  [KnownError.FeedgenDoesNotExist]: `Hmmm, we're having trouble finding this feed. It may have been deleted.`,
-  [KnownError.FeedgenMisconfigured]:
-    'Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue.',
-  [KnownError.FeedgenBadResponse]:
-    'Hmm, the feed server gave a bad response. Please let the feed owner know about this issue.',
-  [KnownError.FeedgenOffline]:
-    'Hmm, the feed server appears to be offline. Please let the feed owner know about this issue.',
-  [KnownError.FeedgenUnknown]:
-    'Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue.',
+export enum KnownError {
+  Block = 'Block',
+  FeedgenDoesNotExist = 'FeedgenDoesNotExist',
+  FeedgenMisconfigured = 'FeedgenMisconfigured',
+  FeedgenBadResponse = 'FeedgenBadResponse',
+  FeedgenOffline = 'FeedgenOffline',
+  FeedgenUnknown = 'FeedgenUnknown',
+  FeedNSFPublic = 'FeedNSFPublic',
+  Unknown = 'Unknown',
 }
 
 export function FeedErrorMessage({
-  feed,
+  feedDesc,
+  error,
   onPressTryAgain,
 }: {
-  feed: PostsFeedModel
+  feedDesc: FeedDescriptor
+  error: any
   onPressTryAgain: () => void
 }) {
+  const knownError = React.useMemo(
+    () => detectKnownError(feedDesc, error),
+    [feedDesc, error],
+  )
   if (
-    typeof feed.knownError === 'undefined' ||
-    feed.knownError === KnownError.Unknown
+    typeof knownError !== 'undefined' &&
+    knownError !== KnownError.Unknown &&
+    feedDesc.startsWith('feedgen')
   ) {
+    return <FeedgenErrorMessage feedDesc={feedDesc} knownError={knownError} />
+  }
+
+  if (knownError === KnownError.Block) {
     return (
-      <ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} />
+      <EmptyState
+        icon="ban"
+        message="Posts hidden"
+        style={{paddingVertical: 40}}
+      />
     )
   }
 
-  return <FeedgenErrorMessage feed={feed} knownError={feed.knownError} />
+  return (
+    <ErrorMessage
+      message={cleanError(error)}
+      onPressTryAgain={onPressTryAgain}
+    />
+  )
 }
 
 function FeedgenErrorMessage({
-  feed,
+  feedDesc,
   knownError,
 }: {
-  feed: PostsFeedModel
+  feedDesc: FeedDescriptor
   knownError: KnownError
 }) {
   const pal = usePalette('default')
-  const store = useStores()
+  const {_: _l} = useLingui()
   const navigation = useNavigation<NavigationProp>()
-  const msg = MESSAGES[knownError]
-  const uri = (feed.params as GetCustomFeed.QueryParams).feed
+  const msg = React.useMemo(
+    () =>
+      ({
+        [KnownError.Unknown]: '',
+        [KnownError.Block]: '',
+        [KnownError.FeedgenDoesNotExist]: _l(
+          msgLingui`Hmmm, we're having trouble finding this feed. It may have been deleted.`,
+        ),
+        [KnownError.FeedgenMisconfigured]: _l(
+          msgLingui`Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue.`,
+        ),
+        [KnownError.FeedgenBadResponse]: _l(
+          msgLingui`Hmm, the feed server gave a bad response. Please let the feed owner know about this issue.`,
+        ),
+        [KnownError.FeedgenOffline]: _l(
+          msgLingui`Hmm, the feed server appears to be offline. Please let the feed owner know about this issue.`,
+        ),
+        [KnownError.FeedNSFPublic]: _l(
+          msgLingui`We're sorry, but this content is not viewable without a Bluesky account.`,
+        ),
+        [KnownError.FeedgenUnknown]: _l(
+          msgLingui`Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue.`,
+        ),
+      }[knownError]),
+    [_l, knownError],
+  )
+  const [_, uri] = feedDesc.split('|')
   const [ownerDid] = safeParseFeedgenUri(uri)
+  const {openModal, closeModal} = useModalControls()
+  const {mutateAsync: removeFeed} = useRemoveFeedMutation()
 
   const onViewProfile = React.useCallback(() => {
     navigation.navigate('Profile', {name: ownerDid})
   }, [navigation, ownerDid])
 
   const onRemoveFeed = React.useCallback(async () => {
-    store.shell.openModal({
+    openModal({
       name: 'confirm',
-      title: 'Remove feed',
-      message: 'Remove this feed from your saved feeds?',
+      title: _l(msgLingui`Remove feed`),
+      message: _l(msgLingui`Remove this feed from your saved feeds?`),
       async onPressConfirm() {
         try {
-          await store.preferences.removeSavedFeed(uri)
+          await removeFeed({uri})
         } catch (err) {
           Toast.show(
             'There was an an issue removing this feed. Please check your internet connection and try again.',
@@ -78,10 +128,40 @@ function FeedgenErrorMessage({
         }
       },
       onPressCancel() {
-        store.shell.closeModal()
+        closeModal()
       },
     })
-  }, [store, uri])
+  }, [openModal, closeModal, uri, removeFeed, _l])
+
+  const cta = React.useMemo(() => {
+    switch (knownError) {
+      case KnownError.FeedNSFPublic: {
+        return null
+      }
+      case KnownError.FeedgenDoesNotExist:
+      case KnownError.FeedgenMisconfigured:
+      case KnownError.FeedgenBadResponse:
+      case KnownError.FeedgenOffline:
+      case KnownError.FeedgenUnknown: {
+        return (
+          <View style={{flexDirection: 'row', alignItems: 'center', gap: 10}}>
+            {knownError === KnownError.FeedgenDoesNotExist && (
+              <Button
+                type="inverted"
+                label="Remove feed"
+                onPress={onRemoveFeed}
+              />
+            )}
+            <Button
+              type="default-light"
+              label="View profile"
+              onPress={onViewProfile}
+            />
+          </View>
+        )
+      }
+    }
+  }, [knownError, onViewProfile, onRemoveFeed])
 
   return (
     <View
@@ -96,16 +176,7 @@ function FeedgenErrorMessage({
         },
       ]}>
       <Text style={pal.text}>{msg}</Text>
-      <View style={{flexDirection: 'row', alignItems: 'center', gap: 10}}>
-        {knownError === KnownError.FeedgenDoesNotExist && (
-          <Button type="inverted" label="Remove feed" onPress={onRemoveFeed} />
-        )}
-        <Button
-          type="default-light"
-          label="View profile"
-          onPress={onViewProfile}
-        />
-      </View>
+      {cta}
     </View>
   )
 }
@@ -118,3 +189,48 @@ function safeParseFeedgenUri(uri: string): [string, string] {
     return ['', '']
   }
 }
+
+function detectKnownError(
+  feedDesc: FeedDescriptor,
+  error: any,
+): KnownError | undefined {
+  if (!error) {
+    return undefined
+  }
+  if (
+    error instanceof AppBskyFeedGetAuthorFeed.BlockedActorError ||
+    error instanceof AppBskyFeedGetAuthorFeed.BlockedByActorError
+  ) {
+    return KnownError.Block
+  }
+  if (typeof error !== 'string') {
+    error = error.toString()
+  }
+  if (!feedDesc.startsWith('feedgen')) {
+    return KnownError.Unknown
+  }
+  if (error.includes('could not find feed')) {
+    return KnownError.FeedgenDoesNotExist
+  }
+  if (error.includes('feed unavailable')) {
+    return KnownError.FeedgenOffline
+  }
+  if (error.includes('invalid did document')) {
+    return KnownError.FeedgenMisconfigured
+  }
+  if (error.includes('could not resolve did document')) {
+    return KnownError.FeedgenMisconfigured
+  }
+  if (
+    error.includes('invalid feed generator service details in did document')
+  ) {
+    return KnownError.FeedgenMisconfigured
+  }
+  if (error.includes('feed provided an invalid response')) {
+    return KnownError.FeedgenBadResponse
+  }
+  if (error.includes(KnownError.FeedNSFPublic)) {
+    return KnownError.FeedNSFPublic
+  }
+  return KnownError.FeedgenUnknown
+}