import { useCallback, useMemo } from 'react'; import type { FC, KeyboardEvent, MouseEvent, MouseEventHandler } from 'react'; import { useIntl } from 'react-intl'; import classNames from 'classnames'; import { quoteComposeById } from '@/flavours/glitch/actions/compose_typed'; import { toggleReblog } from '@/flavours/glitch/actions/interactions'; import { openModal } from '@/flavours/glitch/actions/modal'; import type { ActionMenuItem } from '@/flavours/glitch/models/dropdown_menu'; import type { Status } from '@/flavours/glitch/models/status'; import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store'; import { isFeatureEnabled } from '@/flavours/glitch/utils/environment'; import type { SomeRequired } from '@/flavours/glitch/utils/types'; import type { RenderItemFn, RenderItemFnHandlers } from '../dropdown_menu'; import { Dropdown, DropdownMenuItemContent } from '../dropdown_menu'; import { IconButton } from '../icon_button'; import { boostItemState, messages, quoteItemState, selectStatusState, } from './boost_button_utils'; const renderMenuItem: RenderItemFn = ( item, index, handlers, focusRefCallback, ) => ( ); interface ReblogButtonProps { status: Status; counters?: boolean; } type ActionMenuItemWithIcon = SomeRequired; export const StatusBoostButton: FC = ({ status, counters, }) => { const intl = useIntl(); const dispatch = useAppDispatch(); const statusState = useAppSelector((state) => selectStatusState(state, status), ); const { isLoggedIn, isReblogged, isReblogAllowed, isQuoteAutomaticallyAccepted, isQuoteManuallyAccepted, } = statusState; const isMenuDisabled = !isQuoteAutomaticallyAccepted && !isQuoteManuallyAccepted && !isReblogAllowed; const statusId = status.get('id') as string; const wasBoosted = !!status.get('reblogged'); const showLoginPrompt = useCallback(() => { dispatch( openModal({ modalType: 'INTERACTION', modalProps: { accountId: status.getIn(['account', 'id']), url: status.get('uri'), }, }), ); }, [dispatch, status]); const items = useMemo(() => { const boostItem = boostItemState(statusState); const quoteItem = quoteItemState(statusState); return [ { text: intl.formatMessage(boostItem.title), description: boostItem.meta ? intl.formatMessage(boostItem.meta) : undefined, icon: boostItem.iconComponent, highlighted: wasBoosted, disabled: boostItem.disabled, action: (event) => { dispatch(toggleReblog(statusId, event.shiftKey)); }, }, { text: intl.formatMessage(quoteItem.title), description: quoteItem.meta ? intl.formatMessage(quoteItem.meta) : undefined, icon: quoteItem.iconComponent, disabled: quoteItem.disabled, action: () => { dispatch(quoteComposeById(statusId)); }, }, ] satisfies [ActionMenuItemWithIcon, ActionMenuItemWithIcon]; }, [dispatch, intl, statusId, statusState, wasBoosted]); const boostIcon = items[0].icon; const handleDropdownOpen = useCallback( (event: MouseEvent | KeyboardEvent) => { if (!isLoggedIn) { showLoginPrompt(); return false; } if (event.shiftKey) { dispatch(toggleReblog(status.get('id'), true)); return false; } return true; }, [dispatch, isLoggedIn, showLoginPrompt, status], ); return ( ); }; interface ReblogMenuItemProps { item: ActionMenuItem; index: number; handlers: RenderItemFnHandlers; focusRefCallback?: (c: HTMLAnchorElement | HTMLButtonElement | null) => void; } const ReblogMenuItem: FC = ({ index, item, handlers, focusRefCallback, }) => { const { text, highlighted, disabled } = item; return (
  • ); }; // Legacy helpers // Switch between the legacy and new reblog button based on feature flag. export const BoostButton: FC = (props) => { if (isFeatureEnabled('outgoing_quotes')) { return ; } return ; }; export const LegacyReblogButton: FC = ({ status, counters, }) => { const intl = useIntl(); const statusState = useAppSelector((state) => selectStatusState(state, status), ); const { title, meta, iconComponent, disabled } = useMemo( () => boostItemState(statusState), [statusState], ); const dispatch = useAppDispatch(); const handleClick: MouseEventHandler = useCallback( (event) => { if (statusState.isLoggedIn) { dispatch(toggleReblog(status.get('id') as string, event.shiftKey)); } else { dispatch( openModal({ modalType: 'INTERACTION', modalProps: { accountId: status.getIn(['account', 'id']), url: status.get('uri'), }, }), ); } }, [dispatch, status, statusState.isLoggedIn], ); return ( ); };