import classNames from 'clsx'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { patchMe } from 'soapbox/actions/me'; import snackbar from 'soapbox/actions/snackbar'; import StillImage from 'soapbox/components/still-image'; import { Avatar, Button, Card, CardBody, Icon, Spinner, Stack, Text } from 'soapbox/components/ui'; import { useOwnAccount } from 'soapbox/hooks'; import resizeImage from 'soapbox/utils/resize-image'; import type { AxiosError } from 'axios'; const messages = defineMessages({ header: { id: 'account.header.alt', defaultMessage: 'Profile header' }, error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' }, }); /** Default header filenames from various backends */ const DEFAULT_HEADERS = [ '/headers/original/missing.png', // Mastodon '/images/banner.png', // Pleroma ]; /** Check if the avatar is a default avatar */ const isDefaultHeader = (url: string) => { return DEFAULT_HEADERS.every(header => url.endsWith(header)); }; const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => { const intl = useIntl(); const dispatch = useDispatch(); const account = useOwnAccount(); const fileInput = React.useRef(null); const [selectedFile, setSelectedFile] = React.useState(); const [isSubmitting, setSubmitting] = React.useState(false); const [isDisabled, setDisabled] = React.useState(true); const isDefault = account ? isDefaultHeader(account.header) : false; const openFilePicker = () => { fileInput.current?.click(); }; const handleFileChange = (event: React.ChangeEvent) => { const maxPixels = 1920 * 1080; const rawFile = event.target.files?.item(0); if (!rawFile) return; resizeImage(rawFile, maxPixels).then((file) => { const url = file ? URL.createObjectURL(file) : account?.header as string; setSelectedFile(url); setSubmitting(true); const formData = new FormData(); formData.append('header', file); const credentials = dispatch(patchMe(formData)); Promise.all([credentials]).then(() => { setDisabled(false); setSubmitting(false); onNext(); }).catch((error: AxiosError) => { setSubmitting(false); setDisabled(false); setSelectedFile(null); if (error.response?.status === 422) { dispatch(snackbar.error((error.response.data as any).error.replace('Validation failed: ', ''))); } else { dispatch(snackbar.error(messages.error)); } }); }).catch(console.error); }; return (
{selectedFile || account?.header && ( )} {isSubmitting && (
)}
{account && ( )} {account?.display_name} @{account?.username}
{isDisabled && ( )}
); }; export default CoverPhotoSelectionStep;