Something went wrong. Try again.
Bluesky app fork with some witchin' additions 💫 forked from jollywhoppers.com/witchsky.app
Something went wrong. Try again.
4.0 kB · 152 lines
TSX
at viewport
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153import {memo} from 'react'import {type Insets} from 'react-native'import {type AppBskyFeedDefs} from '@atproto/api'import {msg, Trans} from '@lingui/macro'import {useLingui} from '@lingui/react'import type React from 'react'
import {useCleanError} from '#/lib/hooks/useCleanError'import {type Shadow} from '#/state/cache/post-shadow'import {useFeedFeedbackContext} from '#/state/feed-feedback'import {useBookmarkMutation} from '#/state/queries/bookmarks/useBookmarkMutation'import {useRequireAuth} from '#/state/session'import {useTheme} from '#/alf'import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash'import * as toast from '#/components/Toast'import {useAnalytics} from '#/analytics'import {PostControlButton, PostControlButtonIcon} from './PostControlButton'
export const BookmarkButton = memo(function BookmarkButton({ post, big, logContext, hitSlop,}: { post: Shadow<AppBskyFeedDefs.PostView> big?: boolean logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' hitSlop?: Insets}): React.ReactNode { const t = useTheme() const ax = useAnalytics() const {_} = useLingui() const {mutateAsync: bookmark} = useBookmarkMutation() const cleanError = useCleanError() const requireAuth = useRequireAuth() const {feedDescriptor} = useFeedFeedbackContext()
const {viewer} = post const isBookmarked = !!viewer?.bookmarked
const undoLabel = _( msg({ message: `Undo`, context: `Button label to undo saving/removing a post from saved posts.`, }), )
const save = async ({disableUndo}: {disableUndo?: boolean} = {}) => { try { await bookmark({ action: 'create', post, })
ax.metric('post:bookmark', { uri: post.uri, authorDid: post.author.did, logContext, feedDescriptor, })
toast.show( <toast.Outer> <toast.Icon /> <toast.Text> <Trans>Post saved</Trans> </toast.Text> {!disableUndo && ( <toast.Action label={undoLabel} onPress={() => remove({disableUndo: true})}> {undoLabel} </toast.Action> )} </toast.Outer>, { type: 'success', }, ) } catch (e: any) { const {raw, clean} = cleanError(e) toast.show(clean || raw || e, { type: 'error', }) } }
const remove = async ({disableUndo}: {disableUndo?: boolean} = {}) => { try { await bookmark({ action: 'delete', uri: post.uri, })
ax.metric('post:unbookmark', { uri: post.uri, authorDid: post.author.did, logContext, feedDescriptor, })
toast.show( <toast.Outer> <toast.Icon icon={TrashIcon} /> <toast.Text> <Trans>Removed from saved posts</Trans> </toast.Text> {!disableUndo && ( <toast.Action label={undoLabel} onPress={() => save({disableUndo: true})}> {undoLabel} </toast.Action> )} </toast.Outer>, ) } catch (e: any) { const {raw, clean} = cleanError(e) toast.show(clean || raw || e, { type: 'error', }) } }
const onHandlePress = () => requireAuth(async () => { if (isBookmarked) { await remove() } else { await save() } })
return ( <PostControlButton testID="postBookmarkBtn" big={big} label={ isBookmarked ? _(msg`Remove from saved posts`) : _(msg`Add to saved posts`) } onPress={onHandlePress} hitSlop={hitSlop}> <PostControlButtonIcon fill={isBookmarked ? t.palette.primary_500 : undefined} icon={isBookmarked ? BookmarkFilled : Bookmark} /> </PostControlButton> )})