about summary refs log tree commit diff
path: root/src/view/com/composer
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/composer')
-rw-r--r--src/view/com/composer/Composer.tsx88
-rw-r--r--src/view/com/composer/ComposerReplyTo.tsx16
-rw-r--r--src/view/com/composer/ExternalEmbed.tsx13
-rw-r--r--src/view/com/composer/Prompt.tsx16
-rw-r--r--src/view/com/composer/char-progress/CharProgress.tsx9
-rw-r--r--src/view/com/composer/labels/LabelsBtn.tsx15
-rw-r--r--src/view/com/composer/photos/Gallery.tsx23
-rw-r--r--src/view/com/composer/photos/OpenCameraBtn.tsx19
-rw-r--r--src/view/com/composer/photos/SelectPhotoBtn.tsx14
-rw-r--r--src/view/com/composer/select-language/SelectLangBtn.tsx22
-rw-r--r--src/view/com/composer/select-language/SuggestedLanguage.tsx24
-rw-r--r--src/view/com/composer/text-input/TextInput.tsx35
-rw-r--r--src/view/com/composer/text-input/TextInput.web.tsx32
-rw-r--r--src/view/com/composer/text-input/mobile/Autocomplete.tsx12
-rw-r--r--src/view/com/composer/text-input/web/Autocomplete.tsx20
-rw-r--r--src/view/com/composer/text-input/web/EmojiPicker.web.tsx3
-rw-r--r--src/view/com/composer/text-input/web/LinkDecorator.ts5
-rw-r--r--src/view/com/composer/text-input/web/TagDecorator.ts4
-rw-r--r--src/view/com/composer/threadgate/ThreadgateBtn.tsx13
-rw-r--r--src/view/com/composer/useExternalLinkFetch.ts17
20 files changed, 189 insertions, 211 deletions
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 57be93ca7..2855d4232 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -1,21 +1,5 @@
-import {RichText} from '@atproto/api'
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {useAnalytics} from 'lib/analytics/analytics'
-import * as apilib from 'lib/api/index'
-import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
-import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
-import {usePalette} from 'lib/hooks/usePalette'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {cleanError} from 'lib/strings/errors'
-import {insertMentionAt} from 'lib/strings/mention-manip'
-import {shortenLinks} from 'lib/strings/rich-text-manip'
-import {toShortUrl} from 'lib/strings/url-helpers'
-import {colors, gradients, s} from 'lib/styles'
-import {observer} from 'mobx-react-lite'
-import {isAndroid, isIOS, isNative, isWeb} from 'platform/detection'
 import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'
+import {observer} from 'mobx-react-lite'
 import {
   ActivityIndicator,
   BackHandler,
@@ -28,43 +12,57 @@ import {
   TouchableOpacity,
   View,
 } from 'react-native'
-import LinearGradient from 'react-native-linear-gradient'
 import {useSafeAreaInsets} from 'react-native-safe-area-context'
-import {GalleryModel} from 'state/models/media/gallery'
+import LinearGradient from 'react-native-linear-gradient'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {RichText} from '@atproto/api'
+import {useAnalytics} from 'lib/analytics/analytics'
+import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
+import {ExternalEmbed} from './ExternalEmbed'
+import {Text} from '../util/text/Text'
+import * as Toast from '../util/Toast'
+// TODO: Prevent naming components that coincide with RN primitives
+// due to linting false positives
+import {TextInput, TextInputRef} from './text-input/TextInput'
+import {CharProgress} from './char-progress/CharProgress'
+import {UserAvatar} from '../util/UserAvatar'
+import * as apilib from 'lib/api/index'
 import {ComposerOpts} from 'state/shell/composer'
-import {ComposerReplyTo} from 'view/com/composer/ComposerReplyTo'
-
-import {logger} from '#/logger'
-import {emitPostCreated} from '#/state/events'
-import {useModalControls, useModals} from '#/state/modals'
+import {s, colors, gradients} from 'lib/styles'
+import {cleanError} from 'lib/strings/errors'
+import {shortenLinks} from 'lib/strings/rich-text-manip'
+import {toShortUrl} from 'lib/strings/url-helpers'
+import {SelectPhotoBtn} from './photos/SelectPhotoBtn'
+import {OpenCameraBtn} from './photos/OpenCameraBtn'
+import {ThreadgateBtn} from './threadgate/ThreadgateBtn'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {useExternalLinkFetch} from './useExternalLinkFetch'
+import {isWeb, isNative, isAndroid, isIOS} from 'platform/detection'
+import QuoteEmbed from '../util/post-embeds/QuoteEmbed'
+import {GalleryModel} from 'state/models/media/gallery'
+import {Gallery} from './photos/Gallery'
+import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
+import {LabelsBtn} from './labels/LabelsBtn'
+import {SelectLangBtn} from './select-language/SelectLangBtn'
+import {SuggestedLanguage} from './select-language/SuggestedLanguage'
+import {insertMentionAt} from 'lib/strings/mention-manip'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useModals, useModalControls} from '#/state/modals'
 import {useRequireAltTextEnabled} from '#/state/preferences'
 import {
-  toPostLanguages,
   useLanguagePrefs,
   useLanguagePrefsApi,
+  toPostLanguages,
 } from '#/state/preferences/languages'
+import {useSession, getAgent} from '#/state/session'
 import {useProfileQuery} from '#/state/queries/profile'
-import {ThreadgateSetting} from '#/state/queries/threadgate'
-import {getAgent, useSession} from '#/state/session'
 import {useComposerControls} from '#/state/shell/composer'
-
-import QuoteEmbed from '../util/post-embeds/QuoteEmbed'
-import {Text} from '../util/text/Text'
-import * as Toast from '../util/Toast'
-import {UserAvatar} from '../util/UserAvatar'
-import {CharProgress} from './char-progress/CharProgress'
-import {ExternalEmbed} from './ExternalEmbed'
-import {LabelsBtn} from './labels/LabelsBtn'
-import {Gallery} from './photos/Gallery'
-import {OpenCameraBtn} from './photos/OpenCameraBtn'
-import {SelectPhotoBtn} from './photos/SelectPhotoBtn'
-import {SelectLangBtn} from './select-language/SelectLangBtn'
-import {SuggestedLanguage} from './select-language/SuggestedLanguage'
-// TODO: Prevent naming components that coincide with RN primitives
-// due to linting false positives
-import {TextInput, TextInputRef} from './text-input/TextInput'
-import {ThreadgateBtn} from './threadgate/ThreadgateBtn'
-import {useExternalLinkFetch} from './useExternalLinkFetch'
+import {emitPostCreated} from '#/state/events'
+import {ThreadgateSetting} from '#/state/queries/threadgate'
+import {logger} from '#/logger'
+import {ComposerReplyTo} from 'view/com/composer/ComposerReplyTo'
 
 type Props = ComposerOpts
 export const ComposePost = observer(function ComposePost({
diff --git a/src/view/com/composer/ComposerReplyTo.tsx b/src/view/com/composer/ComposerReplyTo.tsx
index e6fe11565..39a1473a3 100644
--- a/src/view/com/composer/ComposerReplyTo.tsx
+++ b/src/view/com/composer/ComposerReplyTo.tsx
@@ -1,21 +1,21 @@
+import React from 'react'
+import {LayoutAnimation, Pressable, StyleSheet, View} from 'react-native'
+import {Image} from 'expo-image'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {
   AppBskyEmbedImages,
   AppBskyEmbedRecord,
   AppBskyEmbedRecordWithMedia,
   AppBskyFeedPost,
 } from '@atproto/api'
-import {msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {Image} from 'expo-image'
+import {ComposerOptsPostRef} from 'state/shell/composer'
 import {usePalette} from 'lib/hooks/usePalette'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
-import React from 'react'
-import {LayoutAnimation, Pressable, StyleSheet, View} from 'react-native'
-import {ComposerOptsPostRef} from 'state/shell/composer'
-import QuoteEmbed from 'view/com/util/post-embeds/QuoteEmbed'
-import {Text} from 'view/com/util/text/Text'
 import {UserAvatar} from 'view/com/util/UserAvatar'
+import {Text} from 'view/com/util/text/Text'
+import QuoteEmbed from 'view/com/util/post-embeds/QuoteEmbed'
 
 export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
   const pal = usePalette('default')
diff --git a/src/view/com/composer/ExternalEmbed.tsx b/src/view/com/composer/ExternalEmbed.tsx
index c2aebccd6..02dd1bbd7 100644
--- a/src/view/com/composer/ExternalEmbed.tsx
+++ b/src/view/com/composer/ExternalEmbed.tsx
@@ -1,9 +1,3 @@
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {ExternalEmbedDraft} from 'lib/api/index'
-import {usePalette} from 'lib/hooks/usePalette'
-import {s} from 'lib/styles'
 import React from 'react'
 import {
   ActivityIndicator,
@@ -11,9 +5,14 @@ import {
   TouchableOpacity,
   View,
 } from 'react-native'
-
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {AutoSizedImage} from '../util/images/AutoSizedImage'
 import {Text} from '../util/text/Text'
+import {s} from 'lib/styles'
+import {usePalette} from 'lib/hooks/usePalette'
+import {ExternalEmbedDraft} from 'lib/api/index'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 export const ExternalEmbed = ({
   link,
diff --git a/src/view/com/composer/Prompt.tsx b/src/view/com/composer/Prompt.tsx
index 5f19a64bd..632bb2634 100644
--- a/src/view/com/composer/Prompt.tsx
+++ b/src/view/com/composer/Prompt.tsx
@@ -1,15 +1,13 @@
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {usePalette} from 'lib/hooks/usePalette'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import React from 'react'
 import {StyleSheet, TouchableOpacity} from 'react-native'
-
-import {useProfileQuery} from '#/state/queries/profile'
-import {useSession} from '#/state/session'
-
-import {Text} from '../util/text/Text'
 import {UserAvatar} from '../util/UserAvatar'
+import {Text} from '../util/text/Text'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useSession} from '#/state/session'
+import {useProfileQuery} from '#/state/queries/profile'
 
 export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
   const {currentAccount} = useSession()
diff --git a/src/view/com/composer/char-progress/CharProgress.tsx b/src/view/com/composer/char-progress/CharProgress.tsx
index 3c5cee492..a3fa78a59 100644
--- a/src/view/com/composer/char-progress/CharProgress.tsx
+++ b/src/view/com/composer/char-progress/CharProgress.tsx
@@ -1,14 +1,13 @@
-import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
-import {usePalette} from 'lib/hooks/usePalette'
-import {s} from 'lib/styles'
 import React from 'react'
 import {View} from 'react-native'
+import {Text} from '../../util/text/Text'
 // @ts-ignore no type definition -prf
 import ProgressCircle from 'react-native-progress/Circle'
 // @ts-ignore no type definition -prf
 import ProgressPie from 'react-native-progress/Pie'
-
-import {Text} from '../../util/text/Text'
+import {s} from 'lib/styles'
+import {usePalette} from 'lib/hooks/usePalette'
+import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
 
 const DANGER_LENGTH = MAX_GRAPHEME_LENGTH
 
diff --git a/src/view/com/composer/labels/LabelsBtn.tsx b/src/view/com/composer/labels/LabelsBtn.tsx
index 11f3d03d3..b880dd330 100644
--- a/src/view/com/composer/labels/LabelsBtn.tsx
+++ b/src/view/com/composer/labels/LabelsBtn.tsx
@@ -1,14 +1,13 @@
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
-import {msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {usePalette} from 'lib/hooks/usePalette'
-import {ShieldExclamation} from 'lib/icons'
-import {isNative} from 'platform/detection'
 import React from 'react'
 import {Keyboard, StyleSheet} from 'react-native'
 import {Button} from 'view/com/util/forms/Button'
-
+import {usePalette} from 'lib/hooks/usePalette'
+import {ShieldExclamation} from 'lib/icons'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
+import {isNative} from 'platform/detection'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 export function LabelsBtn({
diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx
index 380b70c9c..69c8debb0 100644
--- a/src/view/com/composer/photos/Gallery.tsx
+++ b/src/view/com/composer/photos/Gallery.tsx
@@ -1,20 +1,19 @@
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {Image} from 'expo-image'
-import {usePalette} from 'lib/hooks/usePalette'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {Dimensions} from 'lib/media/types'
-import {colors, s} from 'lib/styles'
-import {observer} from 'mobx-react-lite'
-import {isNative} from 'platform/detection'
 import React, {useState} from 'react'
 import {ImageStyle, Keyboard, LayoutChangeEvent} from 'react-native'
-import {StyleSheet, TouchableOpacity, View} from 'react-native'
 import {GalleryModel} from 'state/models/media/gallery'
+import {observer} from 'mobx-react-lite'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {s, colors} from 'lib/styles'
+import {StyleSheet, TouchableOpacity, View} from 'react-native'
+import {Image} from 'expo-image'
 import {Text} from 'view/com/util/text/Text'
-
+import {Dimensions} from 'lib/media/types'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
+import {isNative} from 'platform/detection'
 
 const IMAGE_GAP = 8
 
diff --git a/src/view/com/composer/photos/OpenCameraBtn.tsx b/src/view/com/composer/photos/OpenCameraBtn.tsx
index ce5318a2f..4353704d5 100644
--- a/src/view/com/composer/photos/OpenCameraBtn.tsx
+++ b/src/view/com/composer/photos/OpenCameraBtn.tsx
@@ -1,21 +1,20 @@
+import React, {useCallback} from 'react'
+import {TouchableOpacity, StyleSheet} from 'react-native'
+import * as MediaLibrary from 'expo-media-library'
 import {
   FontAwesomeIcon,
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
-import {msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import * as MediaLibrary from 'expo-media-library'
-import {useAnalytics} from 'lib/analytics/analytics'
-import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants'
 import {usePalette} from 'lib/hooks/usePalette'
-import {useCameraPermission} from 'lib/hooks/usePermissions'
+import {useAnalytics} from 'lib/analytics/analytics'
 import {openCamera} from 'lib/media/picker'
-import {isMobileWeb, isNative} from 'platform/detection'
-import React, {useCallback} from 'react'
-import {StyleSheet, TouchableOpacity} from 'react-native'
+import {useCameraPermission} from 'lib/hooks/usePermissions'
+import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants'
 import {GalleryModel} from 'state/models/media/gallery'
-
+import {isMobileWeb, isNative} from 'platform/detection'
 import {logger} from '#/logger'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = {
   gallery: GalleryModel
diff --git a/src/view/com/composer/photos/SelectPhotoBtn.tsx b/src/view/com/composer/photos/SelectPhotoBtn.tsx
index 1e0e64090..f7fa9502d 100644
--- a/src/view/com/composer/photos/SelectPhotoBtn.tsx
+++ b/src/view/com/composer/photos/SelectPhotoBtn.tsx
@@ -1,17 +1,17 @@
+import React, {useCallback} from 'react'
+import {TouchableOpacity, StyleSheet} from 'react-native'
 import {
   FontAwesomeIcon,
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
-import {msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {useAnalytics} from 'lib/analytics/analytics'
-import {HITSLOP_10} from 'lib/constants'
 import {usePalette} from 'lib/hooks/usePalette'
+import {useAnalytics} from 'lib/analytics/analytics'
 import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
-import {isNative} from 'platform/detection'
-import React, {useCallback} from 'react'
-import {StyleSheet, TouchableOpacity} from 'react-native'
 import {GalleryModel} from 'state/models/media/gallery'
+import {HITSLOP_10} from 'lib/constants'
+import {isNative} from 'platform/detection'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = {
   gallery: GalleryModel
diff --git a/src/view/com/composer/select-language/SelectLangBtn.tsx b/src/view/com/composer/select-language/SelectLangBtn.tsx
index bfcf248ee..78b1e9ba2 100644
--- a/src/view/com/composer/select-language/SelectLangBtn.tsx
+++ b/src/view/com/composer/select-language/SelectLangBtn.tsx
@@ -1,29 +1,27 @@
+import React, {useCallback, useMemo} from 'react'
+import {StyleSheet, Keyboard} from 'react-native'
 import {
   FontAwesomeIcon,
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
-import {msg, t} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import {usePalette} from 'lib/hooks/usePalette'
-import {isNative} from 'platform/detection'
-import React, {useCallback, useMemo} from 'react'
-import {Keyboard, StyleSheet} from 'react-native'
+import {Text} from 'view/com/util/text/Text'
 import {
   DropdownButton,
   DropdownItem,
   DropdownItemButton,
 } from 'view/com/util/forms/DropdownButton'
-import {Text} from 'view/com/util/text/Text'
-
+import {usePalette} from 'lib/hooks/usePalette'
+import {isNative} from 'platform/detection'
+import {codeToLanguageName} from '../../../../locale/helpers'
 import {useModalControls} from '#/state/modals'
 import {
-  hasPostLanguage,
-  toPostLanguages,
   useLanguagePrefs,
   useLanguagePrefsApi,
+  toPostLanguages,
+  hasPostLanguage,
 } from '#/state/preferences/languages'
-
-import {codeToLanguageName} from '../../../../locale/helpers'
+import {t, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export function SelectLangBtn() {
   const pal = usePalette('default')
diff --git a/src/view/com/composer/select-language/SuggestedLanguage.tsx b/src/view/com/composer/select-language/SuggestedLanguage.tsx
index 97a2a9830..0bf62ae0d 100644
--- a/src/view/com/composer/select-language/SuggestedLanguage.tsx
+++ b/src/view/com/composer/select-language/SuggestedLanguage.tsx
@@ -1,24 +1,22 @@
-import {
-  FontAwesomeIcon,
-  FontAwesomeIconStyle,
-} from '@fortawesome/react-native-fontawesome'
-import {msg, Trans} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
-import lande from 'lande'
 import React, {useEffect, useState} from 'react'
 import {StyleSheet, View} from 'react-native'
-
-import {usePalette} from '#/lib/hooks/usePalette'
-import {s} from '#/lib/styles'
+import lande from 'lande'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {Text} from '../../util/text/Text'
+import {Button} from '../../util/forms/Button'
 import {code3ToCode2Strict, codeToLanguageName} from '#/locale/helpers'
 import {
   toPostLanguages,
   useLanguagePrefs,
   useLanguagePrefsApi,
 } from '#/state/preferences/languages'
-
-import {Button} from '../../util/forms/Button'
-import {Text} from '../../util/text/Text'
+import {usePalette} from '#/lib/hooks/usePalette'
+import {s} from '#/lib/styles'
+import {
+  FontAwesomeIcon,
+  FontAwesomeIconStyle,
+} from '@fortawesome/react-native-fontawesome'
 
 // fallbacks for safari
 const onIdle = globalThis.requestIdleCallback || (cb => setTimeout(cb, 1))
diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx
index 435adfa33..20be585c2 100644
--- a/src/view/com/composer/text-input/TextInput.tsx
+++ b/src/view/com/composer/text-input/TextInput.tsx
@@ -1,24 +1,10 @@
-import {AppBskyRichtextFacet, RichText} from '@atproto/api'
-import PasteInput, {
-  PastedFile,
-  PasteInputRef,
-} from '@mattermost/react-native-paste-input'
-import {POST_IMG_MAX} from 'lib/constants'
-import {usePalette} from 'lib/hooks/usePalette'
-import {downloadAndResize} from 'lib/media/manip'
-import {isUriImage} from 'lib/media/util'
-import {cleanError} from 'lib/strings/errors'
-import {getMentionAt, insertMentionAt} from 'lib/strings/mention-manip'
-import {useTheme} from 'lib/ThemeContext'
-import isEqual from 'lodash.isequal'
-import {isIOS} from 'platform/detection'
 import React, {
-  ComponentProps,
   forwardRef,
   useCallback,
-  useMemo,
   useRef,
+  useMemo,
   useState,
+  ComponentProps,
 } from 'react'
 import {
   NativeSyntheticEvent,
@@ -27,9 +13,22 @@ import {
   TextInputSelectionChangeEventData,
   View,
 } from 'react-native'
-import {Text} from 'view/com/util/text/Text'
-
+import PasteInput, {
+  PastedFile,
+  PasteInputRef,
+} from '@mattermost/react-native-paste-input'
+import {AppBskyRichtextFacet, RichText} from '@atproto/api'
+import isEqual from 'lodash.isequal'
 import {Autocomplete} from './mobile/Autocomplete'
+import {Text} from 'view/com/util/text/Text'
+import {cleanError} from 'lib/strings/errors'
+import {getMentionAt, insertMentionAt} from 'lib/strings/mention-manip'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useTheme} from 'lib/ThemeContext'
+import {isUriImage} from 'lib/media/util'
+import {downloadAndResize} from 'lib/media/manip'
+import {POST_IMG_MAX} from 'lib/constants'
+import {isIOS} from 'platform/detection'
 
 export interface TextInputRef {
   focus: () => void
diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index 6b363558a..c62d11201 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -1,30 +1,28 @@
-import {AppBskyRichtextFacet, RichText} from '@atproto/api'
-import {Trans} from '@lingui/macro'
+import React from 'react'
+import {StyleSheet, View} from 'react-native'
+import {RichText, AppBskyRichtextFacet} from '@atproto/api'
+import EventEmitter from 'eventemitter3'
+import {useEditor, EditorContent, JSONContent} from '@tiptap/react'
 import {Document} from '@tiptap/extension-document'
-import Hardbreak from '@tiptap/extension-hard-break'
 import History from '@tiptap/extension-history'
+import Hardbreak from '@tiptap/extension-hard-break'
 import {Mention} from '@tiptap/extension-mention'
 import {Paragraph} from '@tiptap/extension-paragraph'
 import {Placeholder} from '@tiptap/extension-placeholder'
 import {Text as TiptapText} from '@tiptap/extension-text'
-import {generateJSON} from '@tiptap/html'
-import {EditorContent, JSONContent, useEditor} from '@tiptap/react'
-import EventEmitter from 'eventemitter3'
-import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
-import {blobToDataUri, isUriImage} from 'lib/media/util'
 import isEqual from 'lodash.isequal'
-import React from 'react'
-import {StyleSheet, View} from 'react-native'
-import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
-
-import {Portal} from '#/components/Portal'
-import {usePalette} from '#/lib/hooks/usePalette'
-import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
-
-import {Text} from '../../util/text/Text'
 import {createSuggestion} from './web/Autocomplete'
+import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
+import {isUriImage, blobToDataUri} from 'lib/media/util'
 import {Emoji} from './web/EmojiPicker.web'
 import {LinkDecorator} from './web/LinkDecorator'
+import {generateJSON} from '@tiptap/html'
+import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
+import {usePalette} from '#/lib/hooks/usePalette'
+import {Portal} from '#/components/Portal'
+import {Text} from '../../util/text/Text'
+import {Trans} from '@lingui/macro'
+import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
 import {TagDecorator} from './web/TagDecorator'
 
 export interface TextInputRef {
diff --git a/src/view/com/composer/text-input/mobile/Autocomplete.tsx b/src/view/com/composer/text-input/mobile/Autocomplete.tsx
index 1e8b7900b..c400aa48d 100644
--- a/src/view/com/composer/text-input/mobile/Autocomplete.tsx
+++ b/src/view/com/composer/text-input/mobile/Autocomplete.tsx
@@ -1,15 +1,13 @@
-import {AppBskyActorDefs} from '@atproto/api'
-import {Trans} from '@lingui/macro'
+import React, {useEffect, useRef} from 'react'
+import {Animated, TouchableOpacity, StyleSheet, View} from 'react-native'
 import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
 import {usePalette} from 'lib/hooks/usePalette'
-import React, {useEffect, useRef} from 'react'
-import {Animated, StyleSheet, TouchableOpacity, View} from 'react-native'
 import {Text} from 'view/com/util/text/Text'
 import {UserAvatar} from 'view/com/util/UserAvatar'
-
-import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
-
 import {useGrapheme} from '../hooks/useGrapheme'
+import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
+import {Trans} from '@lingui/macro'
+import {AppBskyActorDefs} from '@atproto/api'
 
 export function Autocomplete({
   prefix,
diff --git a/src/view/com/composer/text-input/web/Autocomplete.tsx b/src/view/com/composer/text-input/web/Autocomplete.tsx
index 21fae297c..76058fed3 100644
--- a/src/view/com/composer/text-input/web/Autocomplete.tsx
+++ b/src/view/com/composer/text-input/web/Autocomplete.tsx
@@ -1,11 +1,3 @@
-import {Trans} from '@lingui/macro'
-import {ReactRenderer} from '@tiptap/react'
-import {
-  SuggestionKeyDownProps,
-  SuggestionOptions,
-  SuggestionProps,
-} from '@tiptap/suggestion'
-import {usePalette} from 'lib/hooks/usePalette'
 import React, {
   forwardRef,
   useEffect,
@@ -13,13 +5,19 @@ import React, {
   useState,
 } from 'react'
 import {Pressable, StyleSheet, View} from 'react-native'
+import {ReactRenderer} from '@tiptap/react'
 import tippy, {Instance as TippyInstance} from 'tippy.js'
+import {
+  SuggestionOptions,
+  SuggestionProps,
+  SuggestionKeyDownProps,
+} from '@tiptap/suggestion'
+import {ActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
+import {usePalette} from 'lib/hooks/usePalette'
 import {Text} from 'view/com/util/text/Text'
 import {UserAvatar} from 'view/com/util/UserAvatar'
-
-import {ActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
-
 import {useGrapheme} from '../hooks/useGrapheme'
+import {Trans} from '@lingui/macro'
 
 interface MentionListRef {
   onKeyDown: (props: SuggestionKeyDownProps) => boolean
diff --git a/src/view/com/composer/text-input/web/EmojiPicker.web.tsx b/src/view/com/composer/text-input/web/EmojiPicker.web.tsx
index d918953de..149362116 100644
--- a/src/view/com/composer/text-input/web/EmojiPicker.web.tsx
+++ b/src/view/com/composer/text-input/web/EmojiPicker.web.tsx
@@ -1,12 +1,11 @@
-import Picker from '@emoji-mart/react'
 import React from 'react'
+import Picker from '@emoji-mart/react'
 import {
   StyleSheet,
   TouchableWithoutFeedback,
   useWindowDimensions,
   View,
 } from 'react-native'
-
 import {textInputWebEmitter} from '../TextInput.web'
 
 const HEIGHT_OFFSET = 40
diff --git a/src/view/com/composer/text-input/web/LinkDecorator.ts b/src/view/com/composer/text-input/web/LinkDecorator.ts
index 207dbe7e4..e36ac80e4 100644
--- a/src/view/com/composer/text-input/web/LinkDecorator.ts
+++ b/src/view/com/composer/text-input/web/LinkDecorator.ts
@@ -14,11 +14,12 @@
  * the facet-set.
  */
 
-import {URL_REGEX} from '@atproto/api'
 import {Mark} from '@tiptap/core'
-import {Node as ProsemirrorNode} from '@tiptap/pm/model'
 import {Plugin, PluginKey} from '@tiptap/pm/state'
+import {Node as ProsemirrorNode} from '@tiptap/pm/model'
 import {Decoration, DecorationSet} from '@tiptap/pm/view'
+import {URL_REGEX} from '@atproto/api'
+
 import {isValidDomain} from 'lib/strings/url-helpers'
 
 export const LinkDecorator = Mark.create({
diff --git a/src/view/com/composer/text-input/web/TagDecorator.ts b/src/view/com/composer/text-input/web/TagDecorator.ts
index 9225fd6bf..2bf3184a8 100644
--- a/src/view/com/composer/text-input/web/TagDecorator.ts
+++ b/src/view/com/composer/text-input/web/TagDecorator.ts
@@ -14,11 +14,11 @@
  * the facet-set.
  */
 
-import {TAG_REGEX, TRAILING_PUNCTUATION_REGEX} from '@atproto/api'
 import {Mark} from '@tiptap/core'
-import {Node as ProsemirrorNode} from '@tiptap/pm/model'
 import {Plugin, PluginKey} from '@tiptap/pm/state'
+import {Node as ProsemirrorNode} from '@tiptap/pm/model'
 import {Decoration, DecorationSet} from '@tiptap/pm/view'
+import {TAG_REGEX, TRAILING_PUNCTUATION_REGEX} from '@atproto/api'
 
 function getDecorations(doc: ProsemirrorNode) {
   const decorations: Decoration[] = []
diff --git a/src/view/com/composer/threadgate/ThreadgateBtn.tsx b/src/view/com/composer/threadgate/ThreadgateBtn.tsx
index 0647d4215..ebbc613ff 100644
--- a/src/view/com/composer/threadgate/ThreadgateBtn.tsx
+++ b/src/view/com/composer/threadgate/ThreadgateBtn.tsx
@@ -1,18 +1,17 @@
+import React from 'react'
+import {TouchableOpacity, StyleSheet, Keyboard} from 'react-native'
 import {
   FontAwesomeIcon,
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
-import {msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
+import {usePalette} from 'lib/hooks/usePalette'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {HITSLOP_10} from 'lib/constants'
-import {usePalette} from 'lib/hooks/usePalette'
-import React from 'react'
-import {Keyboard, StyleSheet, TouchableOpacity} from 'react-native'
-
-import {isNative} from '#/platform/detection'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 import {ThreadgateSetting} from '#/state/queries/threadgate'
+import {isNative} from '#/platform/detection'
 
 export function ThreadgateBtn({
   threadgate,
diff --git a/src/view/com/composer/useExternalLinkFetch.ts b/src/view/com/composer/useExternalLinkFetch.ts
index 5daff41ea..54773d565 100644
--- a/src/view/com/composer/useExternalLinkFetch.ts
+++ b/src/view/com/composer/useExternalLinkFetch.ts
@@ -1,25 +1,24 @@
+import {useState, useEffect} from 'react'
+import {ImageModel} from 'state/models/media/image'
 import * as apilib from 'lib/api/index'
-import {POST_IMG_MAX} from 'lib/constants'
+import {getLinkMeta} from 'lib/link-meta/link-meta'
 import {
+  getPostAsQuote,
   getFeedAsEmbed,
   getListAsEmbed,
-  getPostAsQuote,
 } from 'lib/link-meta/bsky'
-import {getLinkMeta} from 'lib/link-meta/link-meta'
 import {downloadAndResize} from 'lib/media/manip'
 import {
+  isBskyPostUrl,
   isBskyCustomFeedUrl,
   isBskyListUrl,
-  isBskyPostUrl,
 } from 'lib/strings/url-helpers'
-import {useEffect, useState} from 'react'
-import {ImageModel} from 'state/models/media/image'
 import {ComposerOpts} from 'state/shell/composer'
-
+import {POST_IMG_MAX} from 'lib/constants'
 import {logger} from '#/logger'
-import {useFetchDid} from '#/state/queries/handle'
-import {useGetPost} from '#/state/queries/post'
 import {getAgent} from '#/state/session'
+import {useGetPost} from '#/state/queries/post'
+import {useFetchDid} from '#/state/queries/handle'
 
 export function useExternalLinkFetch({
   setQuote,