diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/composer/Composer.tsx | 121 | ||||
-rw-r--r-- | src/view/com/composer/state/composer.ts | 65 | ||||
-rw-r--r-- | src/view/com/composer/text-input/TextInput.tsx | 2 |
3 files changed, 109 insertions, 79 deletions
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index ecafea500..87f72ce42 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -42,7 +42,6 @@ import { AppBskyFeedGetPostThread, BskyAgent, } from '@atproto/api' -import {RichText} from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -57,7 +56,6 @@ import {usePalette} from '#/lib/hooks/usePalette' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {logEvent} from '#/lib/statsig/statsig' import {cleanError} from '#/lib/strings/errors' -import {insertMentionAt} from '#/lib/strings/mention-manip' import {shortenLinks} from '#/lib/strings/rich-text-manip' import {colors, s} from '#/lib/styles' import {logger} from '#/logger' @@ -73,11 +71,8 @@ import { useLanguagePrefs, useLanguagePrefsApi, } from '#/state/preferences/languages' -import {createPostgateRecord} from '#/state/queries/postgate/util' import {useProfileQuery} from '#/state/queries/profile' import {Gif} from '#/state/queries/tenor' -import {ThreadgateAllowUISetting} from '#/state/queries/threadgate' -import {threadgateViewToAllowUISetting} from '#/state/queries/threadgate/util' import {useAgent, useSession} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' import {ComposerOpts} from '#/state/shell/composer' @@ -168,35 +163,40 @@ export const ComposePost = ({ const [isProcessing, setIsProcessing] = useState(false) const [processingState, setProcessingState] = useState('') const [error, setError] = useState('') - const [richtext, setRichText] = useState( - new RichText({ - text: initText - ? initText - : initMention - ? insertMentionAt( - `@${initMention}`, - initMention.length + 1, - `${initMention}`, - ) // insert mention if passed in - : '', - }), - ) - const graphemeLength = useMemo(() => { - return shortenLinks(richtext).graphemeLength - }, [richtext]) - // TODO: Move more state here. - const [composerState, dispatch] = useReducer( + const [draft, dispatch] = useReducer( composerReducer, - {initImageUris, initQuoteUri: initQuote?.uri}, + {initImageUris, initQuoteUri: initQuote?.uri, initText, initMention}, createComposerState, ) - + const richtext = draft.richtext + let quote: string | undefined + if (draft.embed.quote) { + quote = draft.embed.quote.uri + } + let images = NO_IMAGES + if (draft.embed.media?.type === 'images') { + images = draft.embed.media.images + } let videoState: VideoState | NoVideoState = NO_VIDEO - if (composerState.embed.media?.type === 'video') { - videoState = composerState.embed.media.video + if (draft.embed.media?.type === 'video') { + videoState = draft.embed.media.video + } + let extGif: Gif | undefined + let extGifAlt: string | undefined + if (draft.embed.media?.type === 'gif') { + extGif = draft.embed.media.gif + extGifAlt = draft.embed.media.alt + } + let extLink: string | undefined + if (draft.embed.link) { + extLink = draft.embed.link.uri } + const graphemeLength = useMemo(() => { + return shortenLinks(richtext).graphemeLength + }, [richtext]) + const selectVideo = React.useCallback( (asset: ImagePickerAsset) => { const abortController = new AbortController() @@ -241,35 +241,8 @@ export const ComposePost = ({ ) const hasVideo = Boolean(videoState.asset || videoState.video) - const [publishOnUpload, setPublishOnUpload] = useState(false) - const [labels, setLabels] = useState<string[]>([]) - const [threadgateAllowUISettings, onChangeThreadgateAllowUISettings] = - useState<ThreadgateAllowUISetting[]>( - threadgateViewToAllowUISetting(undefined), - ) - const [postgate, setPostgate] = useState(createPostgateRecord({post: ''})) - - let quote: string | undefined - if (composerState.embed.quote) { - quote = composerState.embed.quote.uri - } - let images = NO_IMAGES - if (composerState.embed.media?.type === 'images') { - images = composerState.embed.media.images - } - let extGif: Gif | undefined - let extGifAlt: string | undefined - if (composerState.embed.media?.type === 'gif') { - extGif = composerState.embed.media.gif - extGifAlt = composerState.embed.media.alt - } - let extLink: string | undefined - if (composerState.embed.link) { - extLink = composerState.embed.link.uri - } - const onClose = useCallback(() => { closeComposer() }, [closeComposer]) @@ -419,12 +392,8 @@ export const ComposePost = ({ try { postUri = ( await apilib.post(agent, queryClient, { - composerState, // TODO: move more state here. - rawText: richtext.text, + draft: draft, replyTo: replyTo?.uri, - labels, - threadgate: threadgateAllowUISettings, - postgate, onStateChange: setProcessingState, langs: toPostLanguages(langPrefs.postLanguage), }) @@ -497,24 +466,21 @@ export const ComposePost = ({ [ _, agent, - composerState, + draft, extLink, images, graphemeLength, isAltTextRequiredAndMissing, isProcessing, - labels, langPrefs.postLanguage, onClose, onPost, - postgate, quote, initQuote, initQuoteCount, replyTo, richtext.text, setLangPrefs, - threadgateAllowUISettings, videoState.asset, videoState.status, queryClient, @@ -615,8 +581,10 @@ export const ComposePost = ({ ) : ( <View style={[styles.postBtnWrapper]}> <LabelsBtn - labels={labels} - onChange={setLabels} + labels={draft.labels} + onChange={nextLabels => { + dispatch({type: 'update_labels', labels: nextLabels}) + }} hasMedia={hasMedia || Boolean(extLink)} /> {canPost ? ( @@ -698,7 +666,9 @@ export const ComposePost = ({ richtext={richtext} placeholder={selectTextInputPlaceholder} autoFocus - setRichText={setRichText} + setRichText={rt => { + dispatch({type: 'update_richtext', richtext: rt}) + }} onPhotoPasted={onPhotoPasted} onPressPublish={() => onPressPublish()} onNewLink={onNewLink} @@ -734,7 +704,7 @@ export const ComposePost = ({ </View> )} - {!composerState.embed.media && extLink && ( + {!draft.embed.media && extLink && ( <View style={a.relative} key={extLink}> <ExternalEmbedLink uri={extLink} @@ -815,12 +785,17 @@ export const ComposePost = ({ {replyTo ? null : ( <ThreadgateBtn - postgate={postgate} - onChangePostgate={setPostgate} - threadgateAllowUISettings={threadgateAllowUISettings} - onChangeThreadgateAllowUISettings={ - onChangeThreadgateAllowUISettings - } + postgate={draft.postgate} + onChangePostgate={nextPostgate => { + dispatch({type: 'update_postgate', postgate: nextPostgate}) + }} + threadgateAllowUISettings={draft.threadgate} + onChangeThreadgateAllowUISettings={nextThreadgate => { + dispatch({ + type: 'update_threadgate', + threadgate: nextThreadgate, + }) + }} style={bottomBarAnimatedStyle} Portal={Portal.Portal} /> diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts index 6156d3cfa..e37690342 100644 --- a/src/view/com/composer/state/composer.ts +++ b/src/view/com/composer/state/composer.ts @@ -1,12 +1,17 @@ import {ImagePickerAsset} from 'expo-image-picker' +import {AppBskyFeedPostgate, RichText} from '@atproto/api' +import {insertMentionAt} from '#/lib/strings/mention-manip' import { isBskyPostUrl, postUriToRelativePath, toBskyAppUrl, } from '#/lib/strings/url-helpers' import {ComposerImage, createInitialImages} from '#/state/gallery' +import {createPostgateRecord} from '#/state/queries/postgate/util' import {Gif} from '#/state/queries/tenor' +import {threadgateViewToAllowUISetting} from '#/state/queries/threadgate' +import {ThreadgateAllowUISetting} from '#/state/queries/threadgate' import {ComposerOpts} from '#/state/shell/composer' import {createVideoState, VideoAction, videoReducer, VideoState} from './video' @@ -41,12 +46,19 @@ export type EmbedDraft = { link: Link | undefined } -export type ComposerState = { - // TODO: Other draft data. +export type ComposerDraft = { + richtext: RichText + labels: string[] + postgate: AppBskyFeedPostgate.Record + threadgate: ThreadgateAllowUISetting[] embed: EmbedDraft } export type ComposerAction = + | {type: 'update_richtext'; richtext: RichText} + | {type: 'update_labels'; labels: string[]} + | {type: 'update_postgate'; postgate: AppBskyFeedPostgate.Record} + | {type: 'update_threadgate'; threadgate: ThreadgateAllowUISetting[]} | {type: 'embed_add_images'; images: ComposerImage[]} | {type: 'embed_update_image'; image: ComposerImage} | {type: 'embed_remove_image'; image: ComposerImage} @@ -67,10 +79,34 @@ export type ComposerAction = export const MAX_IMAGES = 4 export function composerReducer( - state: ComposerState, + state: ComposerDraft, action: ComposerAction, -): ComposerState { +): ComposerDraft { switch (action.type) { + case 'update_richtext': { + return { + ...state, + richtext: action.richtext, + } + } + case 'update_labels': { + return { + ...state, + labels: action.labels, + } + } + case 'update_postgate': { + return { + ...state, + postgate: action.postgate, + } + } + case 'update_threadgate': { + return { + ...state, + threadgate: action.threadgate, + } + } case 'embed_add_images': { if (action.images.length === 0) { return state @@ -293,12 +329,16 @@ export function composerReducer( } export function createComposerState({ + initText, + initMention, initImageUris, initQuoteUri, }: { + initText: string | undefined + initMention: string | undefined initImageUris: ComposerOpts['imageUris'] initQuoteUri: string | undefined -}): ComposerState { +}): ComposerDraft { let media: ImagesMedia | undefined if (initImageUris?.length) { media = { @@ -317,7 +357,22 @@ export function createComposerState({ } } } + const initRichText = new RichText({ + text: initText + ? initText + : initMention + ? insertMentionAt( + `@${initMention}`, + initMention.length + 1, + `${initMention}`, + ) + : '', + }) return { + richtext: initRichText, + labels: [], + postgate: createPostgateRecord({post: ''}), + threadgate: threadgateViewToAllowUISetting(undefined), embed: { quote, media, diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index 39baa2cb6..43074fa5b 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -43,7 +43,7 @@ export interface TextInputRef { interface TextInputProps extends ComponentProps<typeof RNTextInput> { richtext: RichText placeholder: string - setRichText: (v: RichText | ((v: RichText) => RichText)) => void + setRichText: (v: RichText) => void onPhotoPasted: (uri: string) => void onPressPublish: (richtext: RichText) => Promise<void> onNewLink: (uri: string) => void |