// @flow import { SITE_NAME, ENABLE_FILE_REACTIONS } from 'config'; import * as PAGES from 'constants/pages'; import * as MODALS from 'constants/modal_types'; import * as ICONS from 'constants/icons'; import React from 'react'; import Button from 'component/button'; import FileDownloadLink from 'component/fileDownloadLink'; import { buildURI, COLLECTIONS_CONSTS } from 'lbry-redux'; import * as RENDER_MODES from 'constants/file_render_modes'; import { useIsMobile } from 'effects/use-screensize'; import ClaimSupportButton from 'component/claimSupportButton'; import ClaimCollectionAddButton from 'component/claimCollectionAddButton'; import { useHistory } from 'react-router'; import FileReactions from 'component/fileReactions'; import { Menu, MenuButton, MenuList, MenuItem } from '@reach/menu-button'; import Icon from 'component/common/icon'; import { webDownloadClaim } from 'util/downloadClaim'; type Props = { uri: string, claim: StreamClaim, openModal: (id: string, { uri: string, claimIsMine?: boolean, isSupport?: boolean }) => void, prepareEdit: ({}, string, {}) => void, claimIsMine: boolean, fileInfo: FileListItem, costInfo: ?{ cost: number }, renderMode: string, myChannels: ?Array<ChannelClaim>, doToast: ({ message: string }) => void, clearPlayingUri: () => void, hideRepost?: boolean, isLivestreamClaim: boolean, reactionsDisabled: boolean, download: (string) => void, streamingUrl: ?string, }; function FileActions(props: Props) { const { fileInfo, uri, openModal, claimIsMine, claim, costInfo, renderMode, prepareEdit, myChannels, clearPlayingUri, doToast, hideRepost, isLivestreamClaim, reactionsDisabled, download, streamingUrl, } = props; const { push, location: { pathname, search }, } = useHistory(); const isMobile = useIsMobile(); const webShareable = costInfo && costInfo.cost === 0 && RENDER_MODES.WEB_SHAREABLE_MODES.includes(renderMode); const showDelete = claimIsMine || (fileInfo && (fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0)); const hasChannels = myChannels && myChannels.length > 0; const claimId = claim && claim.claim_id; const { signing_channel: signingChannel } = claim; const channelName = signingChannel && signingChannel.name; const fileName = claim && claim.value && claim.value.source && claim.value.source.name; // We want to use the short form uri for editing // This is what the user is used to seeing, they don't care about the claim id // We will select the claim id before they publish let editUri; if (claimIsMine) { const uriObject: { streamName: string, streamClaimId: string, channelName?: string } = { streamName: claim.name, streamClaimId: claim.claim_id, }; if (channelName) { uriObject.channelName = channelName; } editUri = buildURI(uriObject); } const urlParams = new URLSearchParams(search); const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID); // @if TARGET='web' const [downloadClicked, setDownloadClicked] = React.useState(false); function handleWebDownload() { // download() causes 'streamingUrl' to be populated. download(uri); setDownloadClicked(true); } React.useEffect(() => { if (downloadClicked && streamingUrl) { webDownloadClaim(streamingUrl, fileName); } }, [downloadClicked, streamingUrl, fileName]); // @endif function handleRepostClick() { if (!hasChannels) { clearPlayingUri(); push(`/$/${PAGES.CHANNEL_NEW}?redirect=${pathname}`); doToast({ message: __('A channel is required to repost on %SITE_NAME%', { SITE_NAME }) }); } else { push(`/$/${PAGES.REPOST_NEW}?from=${encodeURIComponent(uri)}&redirect=${pathname}`); } } const lhsSection = ( <> {ENABLE_FILE_REACTIONS && !reactionsDisabled && <FileReactions uri={uri} livestream={isLivestreamClaim} />} <ClaimSupportButton uri={uri} fileAction /> <ClaimCollectionAddButton uri={uri} fileAction /> {!hideRepost && ( <Button button="alt" className="button--file-action" icon={ICONS.REPOST} label={ claim.meta.reposted > 1 ? __(`%repost_total% Reposts`, { repost_total: claim.meta.reposted }) : __('Repost') } description={__('Repost')} requiresAuth={IS_WEB} onClick={handleRepostClick} /> )} <Button className="button--file-action" icon={ICONS.SHARE} label={isMobile ? undefined : __('Share')} title={__('Share')} onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, webShareable, collectionId })} /> </> ); const rhsSection = ( <> {/* @if TARGET='app' */} <FileDownloadLink uri={uri} /> {/* @endif */} {claimIsMine && ( <Button className="button--file-action" icon={ICONS.EDIT} label={isLivestreamClaim ? __('Update') : __('Edit')} navigate={`/$/${PAGES.UPLOAD}`} onClick={() => { prepareEdit(claim, editUri, fileInfo); }} /> )} {showDelete && ( <Button title={__('Remove from your library')} className="button--file-action" icon={ICONS.DELETE} description={__('Delete')} onClick={() => openModal(MODALS.CONFIRM_FILE_REMOVE, { uri })} /> )} {(!isLivestreamClaim || !claimIsMine) && ( <Menu> <MenuButton className="button--file-action" onClick={(e) => { e.stopPropagation(); e.preventDefault(); }} > <Icon size={20} icon={ICONS.MORE} /> </MenuButton> <MenuList className="menu__list"> {/* @if TARGET='web' */} {!isLivestreamClaim && ( <MenuItem className="comment__menu-option" onSelect={handleWebDownload}> <div className="menu__link"> <Icon aria-hidden icon={ICONS.DOWNLOAD} /> {__('Download')} </div> </MenuItem> )} {/* @endif */} {!claimIsMine && ( <MenuItem className="comment__menu-option" onSelect={() => push(`/$/${PAGES.REPORT_CONTENT}?claimId=${claimId}`)} > <div className="menu__link"> <Icon aria-hidden icon={ICONS.REPORT} /> {__('Report content')} </div> </MenuItem> )} </MenuList> </Menu> )} </> ); if (isMobile) { return ( <div className="media__actions"> {lhsSection} {rhsSection} </div> ); } else { return ( <div className="media__actions"> <div className="section__actions section__actions--no-margin"> {lhsSection} {rhsSection} </div> </div> ); } } export default FileActions;