25f8506c41
* remove post from feed after pressing show less * fix text overflow on android * move state up so it won't get recycled away * make type optional
116 lines
3.3 KiB
TypeScript
116 lines
3.3 KiB
TypeScript
import {memo, useMemo, useState} from 'react'
|
|
import {
|
|
Pressable,
|
|
type PressableProps,
|
|
type StyleProp,
|
|
type ViewStyle,
|
|
} from 'react-native'
|
|
import {
|
|
type AppBskyFeedDefs,
|
|
type AppBskyFeedPost,
|
|
type AppBskyFeedThreadgate,
|
|
type RichText as RichTextAPI,
|
|
} from '@atproto/api'
|
|
import {msg} from '@lingui/macro'
|
|
import {useLingui} from '@lingui/react'
|
|
import type React from 'react'
|
|
|
|
import {useTheme} from '#/lib/ThemeContext'
|
|
import {type Shadow} from '#/state/cache/post-shadow'
|
|
import {atoms as a, useTheme as useAlf} from '#/alf'
|
|
import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid'
|
|
import {useMenuControl} from '#/components/Menu'
|
|
import * as Menu from '#/components/Menu'
|
|
import {EventStopper} from '../EventStopper'
|
|
import {PostDropdownMenuItems} from './PostDropdownBtnMenuItems'
|
|
|
|
let PostDropdownBtn = ({
|
|
testID,
|
|
post,
|
|
postFeedContext,
|
|
record,
|
|
richText,
|
|
style,
|
|
hitSlop,
|
|
size,
|
|
timestamp,
|
|
threadgateRecord,
|
|
onShowLess,
|
|
}: {
|
|
testID: string
|
|
post: Shadow<AppBskyFeedDefs.PostView>
|
|
postFeedContext: string | undefined
|
|
record: AppBskyFeedPost.Record
|
|
richText: RichTextAPI
|
|
style?: StyleProp<ViewStyle>
|
|
hitSlop?: PressableProps['hitSlop']
|
|
size?: 'lg' | 'md' | 'sm'
|
|
timestamp: string
|
|
threadgateRecord?: AppBskyFeedThreadgate.Record
|
|
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
|
|
}): React.ReactNode => {
|
|
const theme = useTheme()
|
|
const alf = useAlf()
|
|
const {_} = useLingui()
|
|
const defaultCtrlColor = theme.palette.default.postCtrl
|
|
const menuControl = useMenuControl()
|
|
const [hasBeenOpen, setHasBeenOpen] = useState(false)
|
|
const lazyMenuControl = useMemo(
|
|
() => ({
|
|
...menuControl,
|
|
open() {
|
|
setHasBeenOpen(true)
|
|
// HACK. We need the state update to be flushed by the time
|
|
// menuControl.open() fires but RN doesn't expose flushSync.
|
|
setTimeout(menuControl.open)
|
|
},
|
|
}),
|
|
[menuControl, setHasBeenOpen],
|
|
)
|
|
return (
|
|
<EventStopper onKeyDown={false}>
|
|
<Menu.Root control={lazyMenuControl}>
|
|
<Menu.Trigger label={_(msg`Open post options menu`)}>
|
|
{({props, state}) => {
|
|
return (
|
|
<Pressable
|
|
{...props}
|
|
hitSlop={hitSlop}
|
|
testID={testID}
|
|
style={[
|
|
style,
|
|
a.rounded_full,
|
|
(state.hovered || state.pressed) && [
|
|
alf.atoms.bg_contrast_25,
|
|
],
|
|
]}>
|
|
<DotsHorizontal
|
|
fill={defaultCtrlColor}
|
|
style={{pointerEvents: 'none'}}
|
|
size={size}
|
|
/>
|
|
</Pressable>
|
|
)
|
|
}}
|
|
</Menu.Trigger>
|
|
{hasBeenOpen && (
|
|
// Lazily initialized. Once mounted, they stay mounted.
|
|
<PostDropdownMenuItems
|
|
testID={testID}
|
|
post={post}
|
|
postFeedContext={postFeedContext}
|
|
record={record}
|
|
richText={richText}
|
|
timestamp={timestamp}
|
|
threadgateRecord={threadgateRecord}
|
|
onShowLess={onShowLess}
|
|
/>
|
|
)}
|
|
</Menu.Root>
|
|
</EventStopper>
|
|
)
|
|
}
|
|
|
|
PostDropdownBtn = memo(PostDropdownBtn)
|
|
export {PostDropdownBtn}
|