import React from 'react'
import {View} from 'react-native'
import {AtUri} from '@atproto/api'
import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useHaptics} from '#/lib/haptics'
import {makeProfileLink} from '#/lib/routes/links'
import {makeCustomFeedLink} from '#/lib/routes/links'
import {shareUrl} from '#/lib/sharing'
import {sanitizeHandle} from '#/lib/strings/handles'
import {toShareUrl} from '#/lib/strings/url-helpers'
import {logger} from '#/logger'
import {isWeb} from '#/platform/detection'
import {FeedSourceFeedInfo} from '#/state/queries/feed'
import {useLikeMutation, useUnlikeMutation} from '#/state/queries/like'
import {
useAddSavedFeedsMutation,
usePreferencesQuery,
useRemoveFeedMutation,
useUpdateSavedFeedsMutation,
} from '#/state/queries/preferences'
import {useSession} from '#/state/session'
import {formatCount} from '#/view/com/util/numeric/format'
import * as Toast from '#/view/com/util/Toast'
import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {Divider} from '#/components/Divider'
import {useRichText} from '#/components/hooks/useRichText'
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
import {
Heart2_Filled_Stroke2_Corner0_Rounded as HeartFilled,
Heart2_Stroke2_Corner0_Rounded as Heart,
} from '#/components/icons/Heart2'
import {
Pin_Filled_Corner0_Rounded as PinFilled,
Pin_Stroke2_Corner0_Rounded as Pin,
} from '#/components/icons/Pin'
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link'
import * as Menu from '#/components/Menu'
import {
ReportDialog,
useReportDialogControl,
} from '#/components/moderation/ReportDialog'
import {RichText} from '#/components/RichText'
import {Text} from '#/components/Typography'
export function ProfileFeedHeaderSkeleton() {
const t = useTheme()
return (
)
}
export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
const t = useTheme()
const {_, i18n} = useLingui()
const {hasSession} = useSession()
const {gtMobile} = useBreakpoints()
const infoControl = Dialog.useDialogControl()
const playHaptic = useHaptics()
const {data: preferences} = usePreferencesQuery()
const [likeUri, setLikeUri] = React.useState(info.likeUri || '')
const isLiked = !!likeUri
const likeCount =
isLiked && likeUri ? (info.likeCount || 0) + 1 : info.likeCount || 0
const {mutateAsync: addSavedFeeds, isPending: isAddSavedFeedPending} =
useAddSavedFeedsMutation()
const {mutateAsync: removeFeed, isPending: isRemovePending} =
useRemoveFeedMutation()
const {mutateAsync: updateSavedFeeds, isPending: isUpdateFeedPending} =
useUpdateSavedFeedsMutation()
const isFeedStateChangePending =
isAddSavedFeedPending || isRemovePending || isUpdateFeedPending
const savedFeedConfig = preferences?.savedFeeds?.find(
f => f.value === info.uri,
)
const isSaved = Boolean(savedFeedConfig)
const isPinned = Boolean(savedFeedConfig?.pinned)
const onToggleSaved = React.useCallback(async () => {
try {
playHaptic()
if (savedFeedConfig) {
await removeFeed(savedFeedConfig)
Toast.show(_(msg`Removed from your feeds`))
} else {
await addSavedFeeds([
{
type: 'feed',
value: info.uri,
pinned: false,
},
])
Toast.show(_(msg`Saved to your feeds`))
}
} catch (err) {
Toast.show(
_(
msg`There was an issue updating your feeds, please check your internet connection and try again.`,
),
'xmark',
)
logger.error('Failed to update feeds', {message: err})
}
}, [_, playHaptic, info, removeFeed, addSavedFeeds, savedFeedConfig])
const onTogglePinned = React.useCallback(async () => {
try {
playHaptic()
if (savedFeedConfig) {
const pinned = !savedFeedConfig.pinned
await updateSavedFeeds([
{
...savedFeedConfig,
pinned,
},
])
if (pinned) {
Toast.show(_(msg`Pinned ${info.displayName} to Home`))
} else {
Toast.show(_(msg`Unpinned ${info.displayName} from Home`))
}
} else {
await addSavedFeeds([
{
type: 'feed',
value: info.uri,
pinned: true,
},
])
Toast.show(_(msg`Pinned ${info.displayName} to Home`))
}
} catch (e) {
Toast.show(_(msg`There was an issue contacting the server`), 'xmark')
logger.error('Failed to toggle pinned feed', {message: e})
}
}, [playHaptic, info, _, savedFeedConfig, updateSavedFeeds, addSavedFeeds])
return (
<>
{hasSession && (
{isPinned ? (
{({props}) => {
return (
)
}}
{_(msg`Unpin from home`)}
{isSaved
? _(msg`Remove from my feeds`)
: _(msg`Save to my feeds`)}
) : (
)}
)}
>
)
}
function DialogInner({
info,
likeUri,
setLikeUri,
likeCount,
isPinned,
onTogglePinned,
isFeedStateChangePending,
}: {
info: FeedSourceFeedInfo
likeUri: string
setLikeUri: (uri: string) => void
likeCount: number
isPinned: boolean
onTogglePinned: () => void
isFeedStateChangePending: boolean
}) {
const t = useTheme()
const {_} = useLingui()
const {hasSession} = useSession()
const playHaptic = useHaptics()
const control = Dialog.useDialogContext()
const reportDialogControl = useReportDialogControl()
const [rt] = useRichText(info.description.text)
const {mutateAsync: likeFeed, isPending: isLikePending} = useLikeMutation()
const {mutateAsync: unlikeFeed, isPending: isUnlikePending} =
useUnlikeMutation()
const isLiked = !!likeUri
const feedRkey = React.useMemo(() => new AtUri(info.uri).rkey, [info.uri])
const onToggleLiked = React.useCallback(async () => {
try {
playHaptic()
if (isLiked && likeUri) {
await unlikeFeed({uri: likeUri})
setLikeUri('')
} else {
const res = await likeFeed({uri: info.uri, cid: info.cid})
setLikeUri(res.uri)
}
} catch (err) {
Toast.show(
_(
msg`There was an issue contacting the server, please check your internet connection and try again.`,
),
'xmark',
)
logger.error('Failed to toggle like', {message: err})
}
}, [playHaptic, isLiked, likeUri, unlikeFeed, setLikeUri, likeFeed, info, _])
const onPressShare = React.useCallback(() => {
playHaptic()
const url = toShareUrl(info.route.href)
shareUrl(url)
}, [info, playHaptic])
const onPressReport = React.useCallback(() => {
reportDialogControl.open()
}, [reportDialogControl])
return (
{info.displayName}
By{' '}
control.close()}>
{sanitizeHandle(info.creatorHandle, '@')}
{typeof likeCount === 'number' && (
control.close()}>
Liked by
)}
{hasSession && (
<>
Something wrong? Let us know.
{info.view && (
)}
>
)}
)
}