import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { Comment, setAccount, useAccount, useAccountComment, useAccountSubplebbits, useEditedComment } from '@bitsocialhq/pkc-react-hooks'; import getShortAddress from '../../lib/get-short-address'; import useSubplebbitsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits'; import useSubplebbitsPagesStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits-pages'; import { getLinkMediaInfo } from '../../lib/utils/media-utils'; import { formatMarkdown } from '../../lib/utils/post-utils'; import { isValidURL } from '../../lib/utils/url-utils'; import { isAllView, isCatalogView, isModQueueView, isModView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { useDirectories, useDirectoryByAddress } from '../../hooks/use-directories'; import { useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbit-address'; import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame'; import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline'; import usePublishPost from '../../hooks/use-publish-post'; import usePublishReply from '../../hooks/use-publish-reply'; import { useFileUpload } from '../../hooks/use-file-upload'; import { getShowUploadControls, isWebRuntime } from '../../lib/media-hosting/show-upload-controls'; import useMediaHostingStore from '../../stores/use-media-hosting-store'; import styles from './post-form.module.css'; import capitalize from 'lodash/capitalize'; import debounce from 'lodash/debounce'; // Separate component for offline alert to isolate rerenders from updatingState // Only this component will rerender when updatingState changes, not the whole PostForm const OfflineAlert = ({ subplebbitAddress }: { subplebbitAddress: string | undefined }) => { const subplebbit = useSubplebbitsStore((state) => (subplebbitAddress ? state.subplebbits[subplebbitAddress] : undefined)); const { isOffline, isOnlineStatusLoading, offlineTitle } = useIsSubplebbitOffline(subplebbit); if (!isOffline && !isOnlineStatusLoading) { return null; } return
{offlineTitle}
; }; export const LinkTypePreviewer = ({ link }: { link: string }) => { const { t } = useTranslation(); const mediaInfo = getLinkMediaInfo(link); let type = mediaInfo?.type; const gifFrameUrl = useFetchGifFirstFrame(mediaInfo?.url); if (type === 'gif' && gifFrameUrl !== null) { type = t('animated_gif'); } else if (type === 'gif' && gifFrameUrl === null) { type = t('gif'); } return isValidURL(link) ? type : t('invalid_url'); }; const PostFormActions = ({ variant, t, isInPostView, onPublishReply, onPublishPost, handleUpload, isUploading, showUploadControls, }: { variant: 'reply' | 'post' | 'upload'; t: (key: string) => string; isInPostView: boolean; onPublishReply: () => void; onPublishPost: () => void; handleUpload: () => void; isUploading: boolean; showUploadControls: boolean; }) => { if (variant === 'reply' && isInPostView) { return ( ); } if (variant === 'post' && !isInPostView) { return ; } if (variant === 'upload' && showUploadControls) { return ( ); } return null; }; interface PostFormFieldsProps { t: (key: string) => string; account: ReturnType; displayName: string | undefined; isInPostView: boolean; subjectRef: React.Ref; textRef: React.Ref; urlRef: React.Ref; url: string; lengthError: string | null; handleContentChange: (e: React.ChangeEvent) => void; setPublishPostOptions: (opts: Record) => void; setPublishReplyOptions: (opts: Record) => void; setUrl: (url: string) => void; isUploading: boolean; uploadedFileName: string | null | undefined; showUploadControls: boolean; showSpoilerForPost: boolean; showSpoilerForReply: boolean; isInAllView: boolean; isInSubscriptionsView: boolean; isInModView: boolean; directories: ReturnType; accountSubplebbitAddresses: string[]; subscriptions: string[]; subplebbitAddress: string | undefined; requirePostLinkIsMedia: boolean; onPublishReply: () => void; onPublishPost: () => void; handleUpload: () => void; } const PostFormFields = ({ t, account, displayName, isInPostView, subjectRef, textRef, urlRef, url, lengthError, handleContentChange, setPublishPostOptions, setPublishReplyOptions, setUrl, isUploading, uploadedFileName, showUploadControls, showSpoilerForPost, showSpoilerForReply, isInAllView, isInSubscriptionsView, isInModView, directories, accountSubplebbitAddresses, subscriptions, subplebbitAddress, requirePostLinkIsMedia, onPublishReply, onPublishPost, handleUpload, }: PostFormFieldsProps) => ( <> {t('name')} { const newDisplayName = e.target.value.trim() || undefined; setAccount({ ...account, author: { ...account?.author, displayName: newDisplayName } }); if (isInPostView) { setPublishReplyOptions({ displayName: newDisplayName }); } else { setPublishPostOptions({ displayName: newDisplayName }); } }} /> {!isInPostView && ( {t('subject')} { setPublishPostOptions({ title: e.target.value }); }} /> )} {t('comment')}