diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts
index 905f7af7..1c58a44d 100644
--- a/src/state/models/feed-view.ts
+++ b/src/state/models/feed-view.ts
@@ -3,6 +3,7 @@ import * as GetTimeline from '../../third-party/api/src/client/types/app/bsky/fe
import * as GetAuthorFeed from '../../third-party/api/src/client/types/app/bsky/feed/getAuthorFeed'
import {RootStoreModel} from './root-store'
import * as apilib from '../lib/api'
+import {cleanError} from '../../view/lib/strings'
export class FeedItemMyStateModel {
repost?: string
@@ -254,7 +255,7 @@ export class FeedModel {
this.isLoading = false
this.isRefreshing = false
this.hasLoaded = true
- this.error = err
+ this.error = cleanError(err)
}
// loader functions
@@ -282,7 +283,7 @@ export class FeedModel {
this._replaceAll(res)
this._xIdle()
} catch (e: any) {
- this._xIdle(`Failed to load feed: ${e.toString()}`)
+ this._xIdle(e.toString())
}
}
@@ -293,7 +294,7 @@ export class FeedModel {
this._prependAll(res)
this._xIdle()
} catch (e: any) {
- this._xIdle(`Failed to load feed: ${e.toString()}`)
+ this._xIdle(e.toString())
}
}
diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts
index 72cc17f6..3a91eb32 100644
--- a/src/state/models/notifications-view.ts
+++ b/src/state/models/notifications-view.ts
@@ -4,6 +4,7 @@ import {RootStoreModel} from './root-store'
import {Declaration} from './_common'
import {hasProp} from '../lib/type-guards'
import {APP_BSKY_GRAPH} from '../../third-party/api'
+import {cleanError} from '../../view/lib/strings'
const UNGROUPABLE_REASONS = ['trend', 'assertion']
@@ -215,7 +216,7 @@ export class NotificationsViewModel {
this.isLoading = false
this.isRefreshing = false
this.hasLoaded = true
- this.error = err
+ this.error = cleanError(err)
}
// loader functions
diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx
index a3cac0cd..2b7bb878 100644
--- a/src/view/com/notifications/Feed.tsx
+++ b/src/view/com/notifications/Feed.tsx
@@ -6,11 +6,14 @@ import {
NotificationsViewItemModel,
} from '../../../state/models/notifications-view'
import {FeedItem} from './FeedItem'
+import {ErrorMessage} from '../util/ErrorMessage'
export const Feed = observer(function Feed({
view,
+ onPressTryAgain,
}: {
view: NotificationsViewModel
+ onPressTryAgain?: () => void
}) {
// TODO optimize renderItem or FeedItem, we're getting this notice from RN: -prf
// VirtualizedList: You have a large list that is slow to update - make sure your
@@ -30,7 +33,14 @@ export const Feed = observer(function Feed({
{view.isLoading && !view.isRefreshing && !view.hasContent && (
Loading...
)}
- {view.hasError && {view.error}}
+ {view.hasError && (
+
+ )}
{view.hasContent && (
console.error('Failed to fetch reposted by', err))
}, [uri, view?.params.uri, store])
+ const onRefresh = () => {
+ view?.refresh()
+ }
+
// loading
// =
if (
@@ -57,7 +55,12 @@ export const PostRepostedBy = observer(function PostRepostedBy({
if (view.hasError) {
return (
- {view.error}
+
)
}
diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx
index 0349d342..ee87a6bf 100644
--- a/src/view/com/post-thread/PostThread.tsx
+++ b/src/view/com/post-thread/PostThread.tsx
@@ -8,6 +8,7 @@ import {
import {useStores} from '../../../state'
import {SharePostModel} from '../../../state/models/shell-ui'
import {PostThreadItem} from './PostThreadItem'
+import {ErrorMessage} from '../util/ErrorMessage'
export const PostThread = observer(function PostThread({uri}: {uri: string}) {
const store = useStores()
@@ -50,7 +51,12 @@ export const PostThread = observer(function PostThread({uri}: {uri: string}) {
if (view.hasError) {
return (
- {view.error}
+
)
}
diff --git a/src/view/com/post-thread/PostVotedBy.tsx b/src/view/com/post-thread/PostVotedBy.tsx
index 596a6a1d..ad85d077 100644
--- a/src/view/com/post-thread/PostVotedBy.tsx
+++ b/src/view/com/post-thread/PostVotedBy.tsx
@@ -6,6 +6,7 @@ import {
VotesViewItemModel,
} from '../../../state/models/votes-view'
import {Link} from '../util/Link'
+import {ErrorMessage} from '../util/ErrorMessage'
import {UserAvatar} from '../util/UserAvatar'
import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles'
@@ -31,6 +32,10 @@ export const PostVotedBy = observer(function PostVotedBy({
newView.setup().catch(err => console.error('Failed to fetch voted by', err))
}, [uri, view?.params.uri, store])
+ const onRefresh = () => {
+ view?.refresh()
+ }
+
// loading
// =
if (
@@ -50,7 +55,12 @@ export const PostVotedBy = observer(function PostVotedBy({
if (view.hasError) {
return (
- {view.error}
+
)
}
diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx
index dc341ddd..75b48fad 100644
--- a/src/view/com/posts/Feed.tsx
+++ b/src/view/com/posts/Feed.tsx
@@ -1,6 +1,7 @@
import React, {MutableRefObject} from 'react'
import {observer} from 'mobx-react-lite'
import {Text, View, FlatList, StyleProp, ViewStyle} from 'react-native'
+import {ErrorMessage} from '../util/ErrorMessage'
import {FeedModel, FeedItemModel} from '../../../state/models/feed-view'
import {FeedItem} from './FeedItem'
@@ -8,10 +9,12 @@ export const Feed = observer(function Feed({
feed,
style,
scrollElRef,
+ onPressTryAgain,
}: {
feed: FeedModel
style?: StyleProp
scrollElRef?: MutableRefObject | null>
+ onPressTryAgain?: () => void
}) {
// TODO optimize renderItem or FeedItem, we're getting this notice from RN: -prf
// VirtualizedList: You have a large list that is slow to update - make sure your
@@ -29,7 +32,14 @@ export const Feed = observer(function Feed({
{feed.isLoading && !feed.isRefreshing && !feed.hasContent && (
Loading...
)}
- {feed.hasError && {feed.error}}
+ {feed.hasError && (
+
+ )}
{feed.hasContent && (
)}
- {feed.isEmpty && This feed is empty!}
+ {feed.isEmpty && !feed.hasError && (
+
+ This feed is empty!
+
+ )}
)
})
diff --git a/src/view/com/profile/ProfileFollowers.tsx b/src/view/com/profile/ProfileFollowers.tsx
index 65297ccc..c4e9435d 100644
--- a/src/view/com/profile/ProfileFollowers.tsx
+++ b/src/view/com/profile/ProfileFollowers.tsx
@@ -6,6 +6,7 @@ import {
FollowerItem,
} from '../../../state/models/user-followers-view'
import {Link} from '../util/Link'
+import {ErrorMessage} from '../util/ErrorMessage'
import {UserAvatar} from '../util/UserAvatar'
import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles'
@@ -31,6 +32,10 @@ export const ProfileFollowers = observer(function ProfileFollowers({
.catch(err => console.error('Failed to fetch user followers', err))
}, [name, view?.params.user, store])
+ const onRefresh = () => {
+ view?.refresh()
+ }
+
// loading
// =
if (
@@ -50,7 +55,12 @@ export const ProfileFollowers = observer(function ProfileFollowers({
if (view.hasError) {
return (
- {view.error}
+
)
}
diff --git a/src/view/com/profile/ProfileFollows.tsx b/src/view/com/profile/ProfileFollows.tsx
index 1bdd18f6..9efd58f8 100644
--- a/src/view/com/profile/ProfileFollows.tsx
+++ b/src/view/com/profile/ProfileFollows.tsx
@@ -7,6 +7,7 @@ import {
} from '../../../state/models/user-follows-view'
import {useStores} from '../../../state'
import {Link} from '../util/Link'
+import {ErrorMessage} from '../util/ErrorMessage'
import {UserAvatar} from '../util/UserAvatar'
import {s, colors} from '../../lib/styles'
@@ -31,6 +32,10 @@ export const ProfileFollows = observer(function ProfileFollows({
.catch(err => console.error('Failed to fetch user follows', err))
}, [name, view?.params.user, store])
+ const onRefresh = () => {
+ view?.refresh()
+ }
+
// loading
// =
if (
@@ -50,7 +55,12 @@ export const ProfileFollows = observer(function ProfileFollows({
if (view.hasError) {
return (
- {view.error}
+
)
}
diff --git a/src/view/com/profile/ProfileMembers.tsx b/src/view/com/profile/ProfileMembers.tsx
index 11db0205..75ef18ca 100644
--- a/src/view/com/profile/ProfileMembers.tsx
+++ b/src/view/com/profile/ProfileMembers.tsx
@@ -1,8 +1,9 @@
import React, {useState, useEffect} from 'react'
import {observer} from 'mobx-react-lite'
-import {ActivityIndicator, FlatList, Text, View} from 'react-native'
+import {ActivityIndicator, FlatList, View} from 'react-native'
import {MembersViewModel, MemberItem} from '../../../state/models/members-view'
import {ProfileCard} from './ProfileCard'
+import {ErrorMessage} from '../util/ErrorMessage'
import {useStores} from '../../../state'
export const ProfileMembers = observer(function ProfileMembers({
@@ -24,6 +25,10 @@ export const ProfileMembers = observer(function ProfileMembers({
newView.setup().catch(err => console.error('Failed to fetch members', err))
}, [name, view?.params.actor, store])
+ const onRefresh = () => {
+ view?.refresh()
+ }
+
// loading
// =
if (
@@ -43,7 +48,12 @@ export const ProfileMembers = observer(function ProfileMembers({
if (view.hasError) {
return (
- {view.error}
+
)
}
diff --git a/src/view/com/util/ErrorMessage.tsx b/src/view/com/util/ErrorMessage.tsx
index 834cd598..3f6522b8 100644
--- a/src/view/com/util/ErrorMessage.tsx
+++ b/src/view/com/util/ErrorMessage.tsx
@@ -1,40 +1,66 @@
import React from 'react'
-import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
+import {
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ StyleProp,
+ View,
+ ViewStyle,
+} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {colors} from '../../lib/styles'
+import LinearGradient from 'react-native-linear-gradient'
+import {colors, gradients} from '../../lib/styles'
export function ErrorMessage({
message,
numberOfLines,
+ dark,
+ style,
onPressTryAgain,
}: {
message: string
numberOfLines?: number
+ dark?: boolean
+ style?: StyleProp
onPressTryAgain?: () => void
}) {
- return (
-
-
+ const inner = (
+ <>
+
-
+
{message}
{onPressTryAgain && (
)}
-
+ >
)
+ if (dark) {
+ return (
+
+ {inner}
+
+ )
+ }
+ return {inner}
}
const styles = StyleSheet.create({
@@ -57,11 +83,18 @@ const styles = StyleSheet.create({
justifyContent: 'center',
marginRight: 8,
},
+ darkErrorIcon: {
+ backgroundColor: colors.white,
+ },
message: {
flex: 1,
color: colors.red4,
paddingRight: 10,
},
+ darkMessage: {
+ color: colors.white,
+ fontWeight: '600',
+ },
btn: {
paddingHorizontal: 4,
paddingVertical: 4,
diff --git a/src/view/lib/strings.ts b/src/view/lib/strings.ts
index 19bd5c47..e47863d5 100644
--- a/src/view/lib/strings.ts
+++ b/src/view/lib/strings.ts
@@ -96,3 +96,10 @@ export function enforceLen(str: string, len: number): string {
}
return str
}
+
+export function cleanError(str: string): string {
+ if (str.startsWith('Error: ')) {
+ return str.slice('Error: '.length)
+ }
+ return str
+}
diff --git a/src/view/lib/styles.ts b/src/view/lib/styles.ts
index dfcaeef9..4bea6443 100644
--- a/src/view/lib/styles.ts
+++ b/src/view/lib/styles.ts
@@ -45,6 +45,7 @@ export const colors = {
export const gradients = {
primary: {start: '#db00ff', end: '#ff007a'},
+ error: {start: '#ff007a', end: '#ed0d78'},
purple: {start: colors.pink3, end: colors.purple3},
blue: {start: colors.purple3, end: colors.blue3},
green: {start: colors.blue3, end: colors.green3},
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
index c16eff80..036f7d14 100644
--- a/src/view/screens/Home.tsx
+++ b/src/view/screens/Home.tsx
@@ -51,6 +51,9 @@ export const Home = observer(function Home({
const onCreatePost = () => {
defaultFeedView.loadLatest()
}
+ const onPressTryAgain = () => {
+ defaultFeedView.refresh()
+ }
return (
@@ -63,6 +66,7 @@ export const Home = observer(function Home({
feed={defaultFeedView}
scrollElRef={scrollElRef}
style={{flex: 1}}
+ onPressTryAgain={onPressTryAgain}
/>
diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx
index c82e7cc7..f1084540 100644
--- a/src/view/screens/Notifications.tsx
+++ b/src/view/screens/Notifications.tsx
@@ -36,10 +36,14 @@ export const Notifications = ({visible}: ScreenParams) => {
}
}, [visible, store])
+ const onPressTryAgain = () => {
+ notesView?.refresh()
+ }
+
return (
- {notesView && }
+ {notesView && }
)
}