Revise FeedSourceCard load state to allow deletion for failures (#2172)

* Revise FeedSourceCard load state to allow deletion for failures

* Translate

* Remove test error feed

* Fix missing uri param

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
Eric Bailey 2023-12-11 16:48:22 -06:00 committed by GitHub
parent 586c2417a8
commit 9a59525b73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 41 deletions

View file

@ -32,30 +32,23 @@ export function FeedSourceCard({
showSaveBtn = false,
showDescription = false,
showLikes = false,
LoadingComponent,
pinOnSave = false,
showMinimalPlaceholder,
}: {
feedUri: string
style?: StyleProp<ViewStyle>
showSaveBtn?: boolean
showDescription?: boolean
showLikes?: boolean
LoadingComponent?: JSX.Element
pinOnSave?: boolean
showMinimalPlaceholder?: boolean
}) {
const {data: preferences} = usePreferencesQuery()
const {data: feed} = useFeedSourceInfoQuery({uri: feedUri})
if (!feed || !preferences) {
return LoadingComponent ? (
LoadingComponent
) : (
<FeedLoadingPlaceholder style={{flex: 1}} />
)
}
return (
<FeedSourceCardLoaded
feedUri={feedUri}
feed={feed}
preferences={preferences}
style={style}
@ -63,11 +56,13 @@ export function FeedSourceCard({
showDescription={showDescription}
showLikes={showLikes}
pinOnSave={pinOnSave}
showMinimalPlaceholder={showMinimalPlaceholder}
/>
)
}
export function FeedSourceCardLoaded({
feedUri,
feed,
preferences,
style,
@ -75,14 +70,17 @@ export function FeedSourceCardLoaded({
showDescription = false,
showLikes = false,
pinOnSave = false,
showMinimalPlaceholder,
}: {
feed: FeedSourceInfo
preferences: UsePreferencesQueryResponse
feedUri: string
feed?: FeedSourceInfo
preferences?: UsePreferencesQueryResponse
style?: StyleProp<ViewStyle>
showSaveBtn?: boolean
showDescription?: boolean
showLikes?: boolean
pinOnSave?: boolean
showMinimalPlaceholder?: boolean
}) {
const pal = usePalette('default')
const {_} = useLingui()
@ -95,7 +93,7 @@ export function FeedSourceCardLoaded({
useRemoveFeedMutation()
const {isPending: isPinPending, mutateAsync: pinFeed} = usePinFeedMutation()
const isSaved = Boolean(preferences?.feeds?.saved?.includes(feed.uri))
const isSaved = Boolean(preferences?.feeds?.saved?.includes(feed?.uri || ''))
const onToggleSaved = React.useCallback(async () => {
// Only feeds can be un/saved, lists are handled elsewhere
@ -105,7 +103,7 @@ export function FeedSourceCardLoaded({
openModal({
name: 'confirm',
title: _(msg`Remove from my feeds`),
message: _(msg`Remove ${feed.displayName} from my feeds?`),
message: _(msg`Remove ${feed?.displayName} from my feeds?`),
onPressConfirm: async () => {
try {
await removeFeed({uri: feed.uri})
@ -132,7 +130,70 @@ export function FeedSourceCardLoaded({
}
}, [isSaved, openModal, feed, removeFeed, saveFeed, _, pinOnSave, pinFeed])
if (!feed || !preferences) return null
/*
* LOAD STATE
*
* This state also captures the scenario where a feed can't load for whatever
* reason.
*/
if (!feed || !preferences)
return (
<View
style={[
pal.border,
{
borderTopWidth: showMinimalPlaceholder ? 0 : 1,
flexDirection: 'row',
alignItems: 'center',
flex: 1,
paddingRight: 18,
},
]}>
{showMinimalPlaceholder ? (
<FeedLoadingPlaceholder
style={{flex: 1}}
showTopBorder={false}
showLowerPlaceholder={false}
/>
) : (
<FeedLoadingPlaceholder style={{flex: 1}} showTopBorder={false} />
)}
{showSaveBtn && (
<Pressable
testID={`feed-${feedUri}-toggleSave`}
disabled={isRemovePending}
accessibilityRole="button"
accessibilityLabel={'Remove from my feeds'}
accessibilityHint=""
onPress={() => {
openModal({
name: 'confirm',
title: _(msg`Remove from my feeds`),
message: _(msg`Remove this feed from my feeds?`),
onPressConfirm: async () => {
try {
await removeFeed({uri: feedUri})
// await item.unsave()
Toast.show('Removed from my feeds')
} catch (e) {
Toast.show('There was an issue contacting your server')
logger.error('Failed to unsave feed', {error: e})
}
},
})
}}
hitSlop={15}
style={styles.btn}>
<FontAwesomeIcon
icon={['far', 'trash-can']}
size={19}
color={pal.colors.icon}
/>
</Pressable>
)}
</View>
)
return (
<Pressable

View file

@ -172,6 +172,7 @@ export const ProfileFeedgens = React.forwardRef<
if (preferences) {
return (
<FeedSourceCardLoaded
feedUri={item.uri}
feed={item}
preferences={preferences}
style={styles.item}

View file

@ -214,7 +214,7 @@ export function FeedLoadingPlaceholder({
pal.border,
style,
]}>
<View style={[pal.view, {flexDirection: 'row', marginBottom: 10}]}>
<View style={[pal.view, {flexDirection: 'row'}]}>
<LoadingPlaceholder
width={36}
height={36}
@ -226,7 +226,7 @@ export function FeedLoadingPlaceholder({
</View>
</View>
{showLowerPlaceholder && (
<View style={{paddingHorizontal: 5}}>
<View style={{paddingHorizontal: 5, marginTop: 10}}>
<LoadingPlaceholder
width={260}
height={8}

View file

@ -26,7 +26,6 @@ import {
useUnpinFeedMutation,
useSetSaveFeedsMutation,
} from '#/state/queries/preferences'
import {FeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
const HITSLOP_TOP = {
top: 20,
@ -89,6 +88,7 @@ export function SavedFeeds({}: Props) {
<Trans>Pinned Feeds</Trans>
</Text>
</View>
{preferences?.feeds ? (
!currentFeeds.pinned.length ? (
<View
@ -290,13 +290,7 @@ function ListItem({
feedUri={feedUri}
style={styles.noBorder}
showSaveBtn
LoadingComponent={
<FeedLoadingPlaceholder
style={{flex: 1}}
showLowerPlaceholder={false}
showTopBorder={false}
/>
}
showMinimalPlaceholder
/>
<Pressable
disabled={isPending}