Eric/preferences (#1873)

* Add initial preferences query, couple mutations

* Remove unused

* Clean up labels, migrate getModerationOpts

* Add birth date handling

* Migrate feed prefs

* Migrate thread view prefs

* Migrate homeFeed to use existing key name

* Fix up saved feeds in response, no impl yet

* Migrate saved feeds to new hooks

* Clean up more of preferences

* Fix PreferencesThreads load state

* Fix modal dismissal

* Small spacing fix

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
Eric Bailey 2023-11-12 13:31:11 -06:00 committed by GitHub
parent c8c308e31e
commit 05b728fffc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 1339 additions and 914 deletions

View file

@ -16,6 +16,151 @@ import * as Toast from 'view/com/util/Toast'
import {sanitizeHandle} from 'lib/strings/handles'
import {logger} from '#/logger'
import {useModalControls} from '#/state/modals'
import {
usePreferencesQuery,
useSaveFeedMutation,
useRemoveFeedMutation,
} from '#/state/queries/preferences'
import {useFeedSourceInfoQuery} from '#/state/queries/feed'
export const NewFeedSourceCard = observer(function FeedSourceCardImpl({
feedUri,
style,
showSaveBtn = false,
showDescription = false,
showLikes = false,
}: {
feedUri: string
style?: StyleProp<ViewStyle>
showSaveBtn?: boolean
showDescription?: boolean
showLikes?: boolean
}) {
const pal = usePalette('default')
const navigation = useNavigation<NavigationProp>()
const {openModal} = useModalControls()
const {data: preferences} = usePreferencesQuery()
const {data: info} = useFeedSourceInfoQuery({uri: feedUri})
const {isPending: isSavePending, mutateAsync: saveFeed} =
useSaveFeedMutation()
const {isPending: isRemovePending, mutateAsync: removeFeed} =
useRemoveFeedMutation()
const isSaved = Boolean(preferences?.feeds?.saved?.includes(feedUri))
const onToggleSaved = React.useCallback(async () => {
// Only feeds can be un/saved, lists are handled elsewhere
if (info?.type !== 'feed') return
if (isSaved) {
openModal({
name: 'confirm',
title: 'Remove from my feeds',
message: `Remove ${info?.displayName} 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})
}
},
})
} else {
try {
await saveFeed({uri: feedUri})
Toast.show('Added to my feeds')
} catch (e) {
Toast.show('There was an issue contacting your server')
logger.error('Failed to save feed', {error: e})
}
}
}, [isSaved, openModal, info, feedUri, removeFeed, saveFeed])
if (!info || !preferences) return null
return (
<Pressable
testID={`feed-${info.displayName}`}
accessibilityRole="button"
style={[styles.container, pal.border, style]}
onPress={() => {
if (info.type === 'feed') {
navigation.push('ProfileFeed', {
name: info.creatorDid,
rkey: new AtUri(info.uri).rkey,
})
} else if (info.type === 'list') {
navigation.push('ProfileList', {
name: info.creatorDid,
rkey: new AtUri(info.uri).rkey,
})
}
}}
key={info.uri}>
<View style={[styles.headerContainer]}>
<View style={[s.mr10]}>
<UserAvatar type="algo" size={36} avatar={info.avatar} />
</View>
<View style={[styles.headerTextContainer]}>
<Text style={[pal.text, s.bold]} numberOfLines={3}>
{info.displayName}
</Text>
<Text style={[pal.textLight]} numberOfLines={3}>
{info.type === 'feed' ? 'Feed' : 'List'} by{' '}
{sanitizeHandle(info.creatorHandle, '@')}
</Text>
</View>
{showSaveBtn && info.type === 'feed' && (
<View>
<Pressable
disabled={isSavePending || isRemovePending}
accessibilityRole="button"
accessibilityLabel={
isSaved ? 'Remove from my feeds' : '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 && info.description ? (
<RichText
style={[pal.textLight, styles.description]}
richText={info.description}
numberOfLines={3}
/>
) : null}
{showLikes && info.type === 'feed' ? (
<Text type="sm-medium" style={[pal.text, pal.textLight]}>
Liked by {info.likeCount || 0}{' '}
{pluralize(info.likeCount || 0, 'user')}
</Text>
) : null}
</Pressable>
)
})
export const FeedSourceCard = observer(function FeedSourceCardImpl({
item,