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.tsx33
-rw-r--r--src/view/com/composer/text-input/TextInput.tsx21
-rw-r--r--src/view/com/composer/text-input/TextInput.web.tsx20
-rw-r--r--src/view/com/composer/text-input/mobile/Autocomplete.tsx18
-rw-r--r--src/view/com/composer/text-input/web/Autocomplete.tsx11
-rw-r--r--src/view/com/composer/useExternalLinkFetch.ts2
6 files changed, 53 insertions, 52 deletions
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 65c485a29..4db9a3a32 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -16,7 +16,6 @@ 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 {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
 import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
 import {ExternalEmbed} from './ExternalEmbed'
 import {Text} from '../util/text/Text'
@@ -26,9 +25,8 @@ import * as Toast from '../util/Toast'
 import {TextInput, TextInputRef} from './text-input/TextInput'
 import {CharProgress} from './char-progress/CharProgress'
 import {UserAvatar} from '../util/UserAvatar'
-import {useStores} from 'state/index'
 import * as apilib from 'lib/api/index'
-import {ComposerOpts} from 'state/models/ui/shell'
+import {ComposerOpts} from 'state/shell/composer'
 import {s, colors, gradients} from 'lib/styles'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
@@ -58,6 +56,9 @@ import {
   useLanguagePrefsApi,
   toPostLanguages,
 } from '#/state/preferences/languages'
+import {useSession} from '#/state/session'
+import {useProfileQuery} from '#/state/queries/profile'
+import {useComposerControls} from '#/state/shell/composer'
 
 type Props = ComposerOpts
 export const ComposePost = observer(function ComposePost({
@@ -66,12 +67,14 @@ export const ComposePost = observer(function ComposePost({
   quote: initQuote,
   mention: initMention,
 }: Props) {
+  const {agent, currentAccount} = useSession()
+  const {data: currentProfile} = useProfileQuery({did: currentAccount!.did})
   const {activeModals} = useModals()
   const {openModal, closeModal} = useModalControls()
+  const {closeComposer} = useComposerControls()
   const {track} = useAnalytics()
   const pal = usePalette('default')
   const {isDesktop, isMobile} = useWebMediaQueries()
-  const store = useStores()
   const {_} = useLingui()
   const requireAltTextEnabled = useRequireAltTextEnabled()
   const langPrefs = useLanguagePrefs()
@@ -101,15 +104,10 @@ export const ComposePost = observer(function ComposePost({
   const {extLink, setExtLink} = useExternalLinkFetch({setQuote})
   const [labels, setLabels] = useState<string[]>([])
   const [suggestedLinks, setSuggestedLinks] = useState<Set<string>>(new Set())
-  const gallery = useMemo(() => new GalleryModel(store), [store])
+  const gallery = useMemo(() => new GalleryModel(), [])
   const onClose = useCallback(() => {
-    store.shell.closeComposer()
-  }, [store])
-
-  const autocompleteView = useMemo<UserAutocompleteModel>(
-    () => new UserAutocompleteModel(store),
-    [store],
-  )
+    closeComposer()
+  }, [closeComposer])
 
   const insets = useSafeAreaInsets()
   const viewStyles = useMemo(
@@ -162,11 +160,6 @@ export const ComposePost = observer(function ComposePost({
     }
   }, [onPressCancel])
 
-  // initial setup
-  useEffect(() => {
-    autocompleteView.setup()
-  }, [autocompleteView])
-
   // listen to escape key on desktop web
   const onEscape = useCallback(
     (e: KeyboardEvent) => {
@@ -216,7 +209,7 @@ export const ComposePost = observer(function ComposePost({
     setIsProcessing(true)
 
     try {
-      await apilib.post(store, {
+      await apilib.post(agent, {
         rawText: richtext.text,
         replyTo: replyTo?.uri,
         images: gallery.images,
@@ -224,7 +217,6 @@ export const ComposePost = observer(function ComposePost({
         extLink,
         labels,
         onStateChange: setProcessingState,
-        knownHandles: autocompleteView.knownHandles,
         langs: toPostLanguages(langPrefs.postLanguage),
       })
     } catch (e: any) {
@@ -381,13 +373,12 @@ export const ComposePost = observer(function ComposePost({
               styles.textInputLayout,
               isNative && styles.textInputLayoutMobile,
             ]}>
-            <UserAvatar avatar={store.me.avatar} size={50} />
+            <UserAvatar avatar={currentProfile?.avatar} size={50} />
             <TextInput
               ref={textInput}
               richtext={richtext}
               placeholder={selectTextInputPlaceholder}
               suggestedLinks={suggestedLinks}
-              autocompleteView={autocompleteView}
               autoFocus={true}
               setRichText={setRichText}
               onPhotoPasted={onPhotoPasted}
diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx
index 2810129f6..13fe3a0b3 100644
--- a/src/view/com/composer/text-input/TextInput.tsx
+++ b/src/view/com/composer/text-input/TextInput.tsx
@@ -3,6 +3,7 @@ import React, {
   useCallback,
   useRef,
   useMemo,
+  useState,
   ComponentProps,
 } from 'react'
 import {
@@ -18,7 +19,6 @@ import PasteInput, {
 } from '@mattermost/react-native-paste-input'
 import {AppBskyRichtextFacet, RichText} from '@atproto/api'
 import isEqual from 'lodash.isequal'
-import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
 import {Autocomplete} from './mobile/Autocomplete'
 import {Text} from 'view/com/util/text/Text'
 import {cleanError} from 'lib/strings/errors'
@@ -38,7 +38,6 @@ interface TextInputProps extends ComponentProps<typeof RNTextInput> {
   richtext: RichText
   placeholder: string
   suggestedLinks: Set<string>
-  autocompleteView: UserAutocompleteModel
   setRichText: (v: RichText | ((v: RichText) => RichText)) => void
   onPhotoPasted: (uri: string) => void
   onPressPublish: (richtext: RichText) => Promise<void>
@@ -56,7 +55,6 @@ export const TextInput = forwardRef(function TextInputImpl(
     richtext,
     placeholder,
     suggestedLinks,
-    autocompleteView,
     setRichText,
     onPhotoPasted,
     onSuggestedLinksChanged,
@@ -69,6 +67,7 @@ export const TextInput = forwardRef(function TextInputImpl(
   const textInput = useRef<PasteInputRef>(null)
   const textInputSelection = useRef<Selection>({start: 0, end: 0})
   const theme = useTheme()
+  const [autocompletePrefix, setAutocompletePrefix] = useState('')
 
   React.useImperativeHandle(ref, () => ({
     focus: () => textInput.current?.focus(),
@@ -99,10 +98,9 @@ export const TextInput = forwardRef(function TextInputImpl(
           textInputSelection.current?.start || 0,
         )
         if (prefix) {
-          autocompleteView.setActive(true)
-          autocompleteView.setPrefix(prefix.value)
-        } else {
-          autocompleteView.setActive(false)
+          setAutocompletePrefix(prefix.value)
+        } else if (autocompletePrefix) {
+          setAutocompletePrefix('')
         }
 
         const set: Set<string> = new Set()
@@ -139,7 +137,8 @@ export const TextInput = forwardRef(function TextInputImpl(
     },
     [
       setRichText,
-      autocompleteView,
+      autocompletePrefix,
+      setAutocompletePrefix,
       suggestedLinks,
       onSuggestedLinksChanged,
       onPhotoPasted,
@@ -179,9 +178,9 @@ export const TextInput = forwardRef(function TextInputImpl(
           item,
         ),
       )
-      autocompleteView.setActive(false)
+      setAutocompletePrefix('')
     },
-    [onChangeText, richtext, autocompleteView],
+    [onChangeText, richtext, setAutocompletePrefix],
   )
 
   const textDecorated = useMemo(() => {
@@ -221,7 +220,7 @@ export const TextInput = forwardRef(function TextInputImpl(
         {textDecorated}
       </PasteInput>
       <Autocomplete
-        view={autocompleteView}
+        prefix={autocompletePrefix}
         onSelect={onSelectAutocompleteItem}
       />
     </View>
diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index 35482bc70..7690a5876 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -11,13 +11,15 @@ import {Paragraph} from '@tiptap/extension-paragraph'
 import {Placeholder} from '@tiptap/extension-placeholder'
 import {Text} from '@tiptap/extension-text'
 import isEqual from 'lodash.isequal'
-import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
 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 {ActorAutocomplete} from '#/state/queries/actor-autocomplete'
+import {useSession} from '#/state/session'
+import {useMyFollowsQuery} from '#/state/queries/my-follows'
 
 export interface TextInputRef {
   focus: () => void
@@ -28,7 +30,6 @@ interface TextInputProps {
   richtext: RichText
   placeholder: string
   suggestedLinks: Set<string>
-  autocompleteView: UserAutocompleteModel
   setRichText: (v: RichText | ((v: RichText) => RichText)) => void
   onPhotoPasted: (uri: string) => void
   onPressPublish: (richtext: RichText) => Promise<void>
@@ -43,7 +44,6 @@ export const TextInput = React.forwardRef(function TextInputImpl(
     richtext,
     placeholder,
     suggestedLinks,
-    autocompleteView,
     setRichText,
     onPhotoPasted,
     onPressPublish,
@@ -52,6 +52,16 @@ export const TextInput = React.forwardRef(function TextInputImpl(
   TextInputProps,
   ref,
 ) {
+  const {agent} = useSession()
+  const autocomplete = React.useMemo(
+    () => new ActorAutocomplete(agent),
+    [agent],
+  )
+  const {data: follows} = useMyFollowsQuery()
+  if (follows) {
+    autocomplete.setFollows(follows)
+  }
+
   const modeClass = useColorSchemeStyle('ProseMirror-light', 'ProseMirror-dark')
   const extensions = React.useMemo(
     () => [
@@ -61,7 +71,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
         HTMLAttributes: {
           class: 'mention',
         },
-        suggestion: createSuggestion({autocompleteView}),
+        suggestion: createSuggestion({autocomplete}),
       }),
       Paragraph,
       Placeholder.configure({
@@ -71,7 +81,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
       History,
       Hardbreak,
     ],
-    [autocompleteView, placeholder],
+    [autocomplete, placeholder],
   )
 
   React.useEffect(() => {
diff --git a/src/view/com/composer/text-input/mobile/Autocomplete.tsx b/src/view/com/composer/text-input/mobile/Autocomplete.tsx
index f8335d4b9..9ccd717fb 100644
--- a/src/view/com/composer/text-input/mobile/Autocomplete.tsx
+++ b/src/view/com/composer/text-input/mobile/Autocomplete.tsx
@@ -1,31 +1,33 @@
 import React, {useEffect} from 'react'
 import {Animated, TouchableOpacity, StyleSheet, View} from 'react-native'
 import {observer} from 'mobx-react-lite'
-import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
 import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
 import {usePalette} from 'lib/hooks/usePalette'
 import {Text} from 'view/com/util/text/Text'
 import {UserAvatar} from 'view/com/util/UserAvatar'
 import {useGrapheme} from '../hooks/useGrapheme'
+import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
 
 export const Autocomplete = observer(function AutocompleteImpl({
-  view,
+  prefix,
   onSelect,
 }: {
-  view: UserAutocompleteModel
+  prefix: string
   onSelect: (item: string) => void
 }) {
   const pal = usePalette('default')
   const positionInterp = useAnimatedValue(0)
   const {getGraphemeString} = useGrapheme()
+  const isActive = !!prefix
+  const {data: suggestions} = useActorAutocompleteQuery(prefix)
 
   useEffect(() => {
     Animated.timing(positionInterp, {
-      toValue: view.isActive ? 1 : 0,
+      toValue: isActive ? 1 : 0,
       duration: 200,
       useNativeDriver: true,
     }).start()
-  }, [positionInterp, view.isActive])
+  }, [positionInterp, isActive])
 
   const topAnimStyle = {
     transform: [
@@ -40,10 +42,10 @@ export const Autocomplete = observer(function AutocompleteImpl({
 
   return (
     <Animated.View style={topAnimStyle}>
-      {view.isActive ? (
+      {isActive ? (
         <View style={[pal.view, styles.container, pal.border]}>
-          {view.suggestions.length > 0 ? (
-            view.suggestions.slice(0, 5).map(item => {
+          {suggestions?.length ? (
+            suggestions.slice(0, 5).map(item => {
               // Eventually use an average length
               const MAX_CHARS = 40
               const MAX_HANDLE_CHARS = 20
diff --git a/src/view/com/composer/text-input/web/Autocomplete.tsx b/src/view/com/composer/text-input/web/Autocomplete.tsx
index bbed26d48..c6b773d86 100644
--- a/src/view/com/composer/text-input/web/Autocomplete.tsx
+++ b/src/view/com/composer/text-input/web/Autocomplete.tsx
@@ -12,7 +12,7 @@ import {
   SuggestionProps,
   SuggestionKeyDownProps,
 } from '@tiptap/suggestion'
-import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
+import {ActorAutocomplete} 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'
@@ -23,15 +23,14 @@ interface MentionListRef {
 }
 
 export function createSuggestion({
-  autocompleteView,
+  autocomplete,
 }: {
-  autocompleteView: UserAutocompleteModel
+  autocomplete: ActorAutocomplete
 }): Omit<SuggestionOptions, 'editor'> {
   return {
     async items({query}) {
-      autocompleteView.setActive(true)
-      await autocompleteView.setPrefix(query)
-      return autocompleteView.suggestions.slice(0, 8)
+      await autocomplete.query(query)
+      return autocomplete.suggestions.slice(0, 8)
     },
 
     render: () => {
diff --git a/src/view/com/composer/useExternalLinkFetch.ts b/src/view/com/composer/useExternalLinkFetch.ts
index eda1a6704..9bdd927a6 100644
--- a/src/view/com/composer/useExternalLinkFetch.ts
+++ b/src/view/com/composer/useExternalLinkFetch.ts
@@ -14,7 +14,7 @@ import {
   isBskyCustomFeedUrl,
   isBskyListUrl,
 } from 'lib/strings/url-helpers'
-import {ComposerOpts} from 'state/models/ui/shell'
+import {ComposerOpts} from 'state/shell/composer'
 import {POST_IMG_MAX} from 'lib/constants'
 import {logger} from '#/logger'