diff options
Diffstat (limited to 'src/view/com/feeds/FeedSourceCard.tsx')
-rw-r--r-- | src/view/com/feeds/FeedSourceCard.tsx | 259 |
1 files changed, 130 insertions, 129 deletions
diff --git a/src/view/com/feeds/FeedSourceCard.tsx b/src/view/com/feeds/FeedSourceCard.tsx index 9bd7238df..9300b4159 100644 --- a/src/view/com/feeds/FeedSourceCard.tsx +++ b/src/view/com/feeds/FeedSourceCard.tsx @@ -6,14 +6,11 @@ import {RichText} from '#/components/RichText' import {usePalette} from 'lib/hooks/usePalette' import {s} from 'lib/styles' import {UserAvatar} from '../util/UserAvatar' -import {useNavigation} from '@react-navigation/native' -import {NavigationProp} from 'lib/routes/types' import {pluralize} from 'lib/strings/helpers' import {AtUri} from '@atproto/api' import * as Toast from 'view/com/util/Toast' import {sanitizeHandle} from 'lib/strings/handles' import {logger} from '#/logger' -import {useModalControls} from '#/state/modals' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import { @@ -26,6 +23,8 @@ import { import {useFeedSourceInfoQuery, FeedSourceInfo} from '#/state/queries/feed' import {FeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' import {useTheme} from '#/alf' +import * as Prompt from '#/components/Prompt' +import {useNavigationDeduped} from 'lib/hooks/useNavigationDeduped' export function FeedSourceCard({ feedUri, @@ -86,8 +85,8 @@ export function FeedSourceCardLoaded({ const t = useTheme() const pal = usePalette('default') const {_} = useLingui() - const navigation = useNavigation<NavigationProp>() - const {openModal} = useModalControls() + const removePromptControl = Prompt.usePromptControl() + const navigation = useNavigationDeduped() const {isPending: isSavePending, mutateAsync: saveFeed} = useSaveFeedMutation() @@ -97,40 +96,45 @@ export function FeedSourceCardLoaded({ const isSaved = Boolean(preferences?.feeds?.saved?.includes(feed?.uri || '')) + const onSave = React.useCallback(async () => { + if (!feed) return + + try { + if (pinOnSave) { + await pinFeed({uri: feed.uri}) + } else { + await saveFeed({uri: feed.uri}) + } + Toast.show(_(msg`Added to my feeds`)) + } catch (e) { + Toast.show(_(msg`There was an issue contacting your server`)) + logger.error('Failed to save feed', {message: e}) + } + }, [_, feed, pinFeed, pinOnSave, saveFeed]) + + const onUnsave = React.useCallback(async () => { + if (!feed) return + + try { + await removeFeed({uri: feed.uri}) + // await item.unsave() + Toast.show(_(msg`Removed from my feeds`)) + } catch (e) { + Toast.show(_(msg`There was an issue contacting your server`)) + logger.error('Failed to unsave feed', {message: e}) + } + }, [_, feed, removeFeed]) + const onToggleSaved = React.useCallback(async () => { // Only feeds can be un/saved, lists are handled elsewhere if (feed?.type !== 'feed') return if (isSaved) { - openModal({ - name: 'confirm', - title: _(msg`Remove from my feeds`), - message: _(msg`Remove ${feed?.displayName} from my feeds?`), - onPressConfirm: async () => { - try { - await removeFeed({uri: feed.uri}) - // await item.unsave() - Toast.show(_(msg`Removed from my feeds`)) - } catch (e) { - Toast.show(_(msg`There was an issue contacting your server`)) - logger.error('Failed to unsave feed', {message: e}) - } - }, - }) + removePromptControl.open() } else { - try { - if (pinOnSave) { - await pinFeed({uri: feed.uri}) - } else { - await saveFeed({uri: feed.uri}) - } - Toast.show(_(msg`Added to my feeds`)) - } catch (e) { - Toast.show(_(msg`There was an issue contacting your server`)) - logger.error('Failed to save feed', {message: e}) - } + await onSave() } - }, [isSaved, openModal, feed, removeFeed, saveFeed, _, pinOnSave, pinFeed]) + }, [feed?.type, isSaved, removePromptControl, onSave]) /* * LOAD STATE @@ -168,25 +172,7 @@ export function FeedSourceCardLoaded({ accessibilityRole="button" accessibilityLabel={_(msg`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(_(msg`Removed from my feeds`)) - } catch (e) { - Toast.show( - _(msg`There was an issue contacting your server`), - ) - logger.error('Failed to unsave feed', {message: e}) - } - }, - }) - }} + onPress={onToggleSaved} hitSlop={15} style={styles.btn}> <FontAwesomeIcon @@ -200,89 +186,104 @@ export function FeedSourceCardLoaded({ ) return ( - <Pressable - testID={`feed-${feed.displayName}`} - accessibilityRole="button" - style={[styles.container, pal.border, style]} - onPress={() => { - if (feed.type === 'feed') { - navigation.push('ProfileFeed', { - name: feed.creatorDid, - rkey: new AtUri(feed.uri).rkey, - }) - } else if (feed.type === 'list') { - navigation.push('ProfileList', { - name: feed.creatorDid, - rkey: new AtUri(feed.uri).rkey, - }) - } - }} - key={feed.uri}> - <View style={[styles.headerContainer]}> - <View style={[s.mr10]}> - <UserAvatar type="algo" size={36} avatar={feed.avatar} /> - </View> - <View style={[styles.headerTextContainer]}> - <Text style={[pal.text, s.bold]} numberOfLines={3}> - {feed.displayName} - </Text> - <Text style={[pal.textLight]} numberOfLines={3}> - {feed.type === 'feed' ? ( - <Trans>Feed by {sanitizeHandle(feed.creatorHandle, '@')}</Trans> - ) : ( - <Trans>List by {sanitizeHandle(feed.creatorHandle, '@')}</Trans> - )} - </Text> - </View> - - {showSaveBtn && feed.type === 'feed' && ( - <View style={[s.justifyCenter]}> - <Pressable - testID={`feed-${feed.displayName}-toggleSave`} - disabled={isSavePending || isPinPending || isRemovePending} - accessibilityRole="button" - accessibilityLabel={ - isSaved ? _(msg`Remove from my feeds`) : _(msg`Add to my feeds`) - } - accessibilityHint="" - onPress={onToggleSaved} - hitSlop={15} - style={styles.btn}> - {isSaved ? ( - <FontAwesomeIcon - icon={['far', 'trash-can']} - size={19} - color={pal.colors.icon} - /> + <> + <Pressable + testID={`feed-${feed.displayName}`} + accessibilityRole="button" + style={[styles.container, pal.border, style]} + onPress={() => { + if (feed.type === 'feed') { + navigation.push('ProfileFeed', { + name: feed.creatorDid, + rkey: new AtUri(feed.uri).rkey, + }) + } else if (feed.type === 'list') { + navigation.push('ProfileList', { + name: feed.creatorDid, + rkey: new AtUri(feed.uri).rkey, + }) + } + }} + key={feed.uri}> + <View style={[styles.headerContainer]}> + <View style={[s.mr10]}> + <UserAvatar type="algo" size={36} avatar={feed.avatar} /> + </View> + <View style={[styles.headerTextContainer]}> + <Text style={[pal.text, s.bold]} numberOfLines={3}> + {feed.displayName} + </Text> + <Text style={[pal.textLight]} numberOfLines={3}> + {feed.type === 'feed' ? ( + <Trans>Feed by {sanitizeHandle(feed.creatorHandle, '@')}</Trans> ) : ( - <FontAwesomeIcon - icon="plus" - size={18} - color={pal.colors.link} - /> + <Trans>List by {sanitizeHandle(feed.creatorHandle, '@')}</Trans> )} - </Pressable> + </Text> </View> - )} - </View> - {showDescription && feed.description ? ( - <RichText - style={[t.atoms.text_contrast_high, styles.description]} - value={feed.description} - numberOfLines={3} - /> - ) : null} + {showSaveBtn && feed.type === 'feed' && ( + <View style={[s.justifyCenter]}> + <Pressable + testID={`feed-${feed.displayName}-toggleSave`} + disabled={isSavePending || isPinPending || isRemovePending} + accessibilityRole="button" + accessibilityLabel={ + isSaved + ? _(msg`Remove from my feeds`) + : _(msg`Add to my feeds`) + } + accessibilityHint="" + onPress={onToggleSaved} + hitSlop={15} + style={styles.btn}> + {isSaved ? ( + <FontAwesomeIcon + icon={['far', 'trash-can']} + size={19} + color={pal.colors.icon} + /> + ) : ( + <FontAwesomeIcon + icon="plus" + size={18} + color={pal.colors.link} + /> + )} + </Pressable> + </View> + )} + </View> + + {showDescription && feed.description ? ( + <RichText + style={[t.atoms.text_contrast_high, styles.description]} + value={feed.description} + numberOfLines={3} + /> + ) : null} - {showLikes && feed.type === 'feed' ? ( - <Text type="sm-medium" style={[pal.text, pal.textLight]}> - <Trans> - Liked by {feed.likeCount || 0}{' '} - {pluralize(feed.likeCount || 0, 'user')} - </Trans> - </Text> - ) : null} - </Pressable> + {showLikes && feed.type === 'feed' ? ( + <Text type="sm-medium" style={[pal.text, pal.textLight]}> + <Trans> + Liked by {feed.likeCount || 0}{' '} + {pluralize(feed.likeCount || 0, 'user')} + </Trans> + </Text> + ) : null} + </Pressable> + + <Prompt.Basic + control={removePromptControl} + title={_(msg`Remove from my feeds?`)} + description={_( + msg`Are you sure you want to remove ${feed.displayName} from your feeds?`, + )} + onConfirm={onUnsave} + confirmButtonCta={_(msg`Remove`)} + confirmButtonColor="negative" + /> + </> ) } |