diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 214f3605ec..10169b7063 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -59,7 +59,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 {shortenLinks} from '#/lib/strings/rich-text-manip'
import {colors, s} from '#/lib/styles'
import {logger} from '#/logger'
import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection'
@@ -128,8 +127,6 @@ type CancelRef = {
onPressCancel: () => void
}
-const NO_IMAGES: ComposerImage[] = []
-
type Props = ComposerOpts
export const ComposePost = ({
replyTo,
@@ -178,33 +175,10 @@ export const ComposePost = ({
})
}, [])
- 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 (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) => {
@@ -252,10 +226,9 @@ export const ComposePost = ({
const onPressCancel = useCallback(() => {
if (
- graphemeLength > 0 ||
- images.length !== 0 ||
- extGif ||
- videoState.status !== 'idle'
+ draft.shortenedGraphemeLength > 0 ||
+ draft.embed.media ||
+ draft.embed.link
) {
closeAllDialogs()
Keyboard.dismiss()
@@ -263,15 +236,7 @@ export const ComposePost = ({
} else {
onClose()
}
- }, [
- extGif,
- graphemeLength,
- images.length,
- closeAllDialogs,
- discardPromptControl,
- onClose,
- videoState.status,
- ])
+ }, [draft, closeAllDialogs, discardPromptControl, onClose])
useImperativeHandle(cancelRef, () => ({onPressCancel}))
@@ -296,25 +261,27 @@ export const ComposePost = ({
}, [onPressCancel, closeAllDialogs, closeAllModals])
const isAltTextRequiredAndMissing = useMemo(() => {
- if (!requireAltTextEnabled) return false
-
- if (images.some(img => img.alt === '')) return true
-
- if (extGif && !extGifAlt) return true
-
+ const media = draft.embed.media
+ if (!requireAltTextEnabled || !media) {
+ return false
+ }
+ if (media.type === 'images' && media.images.some(img => !img.alt)) {
+ return true
+ }
+ if (media.type === 'gif' && !media.alt) {
+ return true
+ }
return false
- }, [images, extGifAlt, extGif, requireAltTextEnabled])
+ }, [draft.embed.media, requireAltTextEnabled])
const isEmptyPost =
- richtext.text.trim().length === 0 &&
- images.length === 0 &&
- !extLink &&
- !extGif &&
- !quote &&
- videoState.status === 'idle'
+ draft.richtext.text.trim().length === 0 &&
+ !draft.embed.link &&
+ !draft.embed.media &&
+ !draft.embed.quote
const canPost =
- graphemeLength <= MAX_GRAPHEME_LENGTH &&
+ draft.shortenedGraphemeLength <= MAX_GRAPHEME_LENGTH &&
!isAltTextRequiredAndMissing &&
!isEmptyPost &&
videoState.status !== 'error'
@@ -341,6 +308,11 @@ export const ComposePost = ({
setError('')
setIsPublishing(true)
+ const imageCount =
+ draft.embed.media?.type === 'images'
+ ? draft.embed.media.images.length
+ : 0
+
let postUri
try {
postUri = (
@@ -365,7 +337,7 @@ export const ComposePost = ({
} catch (e: any) {
logger.error(e, {
message: `Composer: create post failed`,
- hasImages: images.length > 0,
+ hasImages: imageCount > 0,
})
let err = cleanError(e.message)
@@ -382,10 +354,10 @@ export const ComposePost = ({
} finally {
if (postUri) {
logEvent('post:create', {
- imageCount: images.length,
- isReply: replyTo != null,
- hasLink: extLink != null,
- hasQuote: quote != null,
+ imageCount,
+ isReply: !!replyTo,
+ hasLink: !!draft.embed.link,
+ hasQuote: !!draft.embed.quote,
langs: langPrefs.postLanguage,
logContext: 'Composer',
})
@@ -422,14 +394,12 @@ export const ComposePost = ({
_,
agent,
composerState.thread,
- extLink,
- images,
+ draft,
canPost,
isPublishing,
langPrefs.postLanguage,
onClose,
onPost,
- quote,
initQuote,
replyTo,
setLangPrefs,
@@ -512,7 +482,7 @@ export const ComposePost = ({
/>
-
+
void
- graphemeLength: number
onEmojiButtonPress: () => void
onError: (error: string) => void
onSelectVideo: (asset: ImagePickerAsset) => void
@@ -1017,7 +984,10 @@ function ComposerFooter({
-
+
)
diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts
index 958718eafa..353600ef60 100644
--- a/src/view/com/composer/state/composer.ts
+++ b/src/view/com/composer/state/composer.ts
@@ -3,6 +3,7 @@ import {AppBskyFeedPostgate, RichText} from '@atproto/api'
import {SelfLabel} from '#/lib/moderation'
import {insertMentionAt} from '#/lib/strings/mention-manip'
+import {shortenLinks} from '#/lib/strings/rich-text-manip'
import {
isBskyPostUrl,
postUriToRelativePath,
@@ -51,6 +52,7 @@ export type PostDraft = {
richtext: RichText
labels: SelfLabel[]
embed: EmbedDraft
+ shortenedGraphemeLength: number
}
export type PostAction =
@@ -137,6 +139,7 @@ function postReducer(state: PostDraft, action: PostAction): PostDraft {
return {
...state,
richtext: action.richtext,
+ shortenedGraphemeLength: shortenLinks(action.richtext).graphemeLength,
}
}
case 'update_labels': {
@@ -425,6 +428,7 @@ export function createComposerState({
posts: [
{
richtext: initRichText,
+ shortenedGraphemeLength: 0,
labels: [],
embed: {
quote,