Improve error messages

This commit is contained in:
Paul Frazee 2022-11-15 10:46:12 -06:00
parent 6e93301542
commit fb3a43c216
15 changed files with 156 additions and 32 deletions

View file

@ -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 && (
<Text>Loading...</Text>
)}
{view.hasError && <Text>{view.error}</Text>}
{view.hasError && (
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onPressTryAgain}
/>
)}
{view.hasContent && (
<FlatList
data={view.notifications}

View file

@ -1,18 +1,12 @@
import React, {useState, useEffect} from 'react'
import {observer} from 'mobx-react-lite'
import {
ActivityIndicator,
FlatList,
Image,
StyleSheet,
Text,
View,
} from 'react-native'
import {ActivityIndicator, FlatList, StyleSheet, Text, View} from 'react-native'
import {
RepostedByViewModel,
RepostedByViewItemModel,
} from '../../../state/models/reposted-by-view'
import {UserAvatar} from '../util/UserAvatar'
import {ErrorMessage} from '../util/ErrorMessage'
import {Link} from '../util/Link'
import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles'
@ -38,6 +32,10 @@ export const PostRepostedBy = observer(function PostRepostedBy({
.catch(err => 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>
<Text>{view.error}</Text>
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onRefresh}
/>
</View>
)
}

View file

@ -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>
<Text>{view.error}</Text>
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onRefresh}
/>
</View>
)
}

View file

@ -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>
<Text>{view.error}</Text>
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onRefresh}
/>
</View>
)
}

View file

@ -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<ViewStyle>
scrollElRef?: MutableRefObject<FlatList<any> | 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 && (
<Text>Loading...</Text>
)}
{feed.hasError && <Text>{feed.error}</Text>}
{feed.hasError && (
<ErrorMessage
dark
message={feed.error}
style={{margin: 6}}
onPressTryAgain={onPressTryAgain}
/>
)}
{feed.hasContent && (
<FlatList
ref={scrollElRef}
@ -41,7 +51,11 @@ export const Feed = observer(function Feed({
onEndReached={onEndReached}
/>
)}
{feed.isEmpty && <Text>This feed is empty!</Text>}
{feed.isEmpty && !feed.hasError && (
<View>
<Text>This feed is empty!</Text>
</View>
)}
</View>
)
})

View file

@ -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>
<Text>{view.error}</Text>
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onRefresh}
/>
</View>
)
}

View file

@ -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>
<Text>{view.error}</Text>
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onRefresh}
/>
</View>
)
}

View file

@ -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>
<Text>{view.error}</Text>
<ErrorMessage
dark
message={view.error}
style={{margin: 6}}
onPressTryAgain={onRefresh}
/>
</View>
)
}

View file

@ -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<ViewStyle>
onPressTryAgain?: () => void
}) {
return (
<View style={styles.outer}>
<View style={styles.errorIcon}>
const inner = (
<>
<View style={[styles.errorIcon, dark ? styles.darkErrorIcon : undefined]}>
<FontAwesomeIcon
icon="exclamation"
style={{color: colors.white}}
style={{color: dark ? colors.red3 : colors.white}}
size={16}
/>
</View>
<Text style={styles.message} numberOfLines={numberOfLines}>
<Text
style={[styles.message, dark ? styles.darkMessage : undefined]}
numberOfLines={numberOfLines}>
{message}
</Text>
{onPressTryAgain && (
<TouchableOpacity style={styles.btn} onPress={onPressTryAgain}>
<FontAwesomeIcon
icon="arrows-rotate"
style={{color: colors.red4}}
style={{color: dark ? colors.white : colors.red4}}
size={16}
/>
</TouchableOpacity>
)}
</View>
</>
)
if (dark) {
return (
<LinearGradient
colors={[gradients.error.start, gradients.error.end]}
start={{x: 0.5, y: 0}}
end={{x: 1, y: 1}}
style={[styles.outer, style]}>
{inner}
</LinearGradient>
)
}
return <View style={[styles.outer, style]}>{inner}</View>
}
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,