about summary refs log tree commit diff
path: root/src/view/shell
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/shell')
-rw-r--r--src/view/shell/Drawer.tsx5
-rw-r--r--src/view/shell/desktop/Search.tsx99
-rw-r--r--src/view/shell/index.tsx2
-rw-r--r--src/view/shell/index.web.tsx2
4 files changed, 86 insertions, 22 deletions
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index 6f748755a..c30874c2f 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
@@ -53,6 +53,8 @@ import {useInviteCodesQuery} from '#/state/queries/invites'
 import {NavSignupCard} from '#/view/shell/NavSignupCard'
 import {TextLink} from '../com/util/Link'
 
+import {useTheme as useAlfTheme} from '#/alf'
+
 let DrawerProfileCard = ({
   account,
   onPressProfile,
@@ -106,6 +108,7 @@ export {DrawerProfileCard}
 
 let DrawerContent = ({}: {}): React.ReactNode => {
   const theme = useTheme()
+  const t = useAlfTheme()
   const pal = usePalette('default')
   const {_} = useLingui()
   const setDrawerOpen = useSetDrawerOpen()
@@ -208,7 +211,7 @@ let DrawerContent = ({}: {}): React.ReactNode => {
       testID="drawer"
       style={[
         styles.view,
-        theme.colorScheme === 'light' ? pal.view : styles.viewDarkMode,
+        theme.colorScheme === 'light' ? pal.view : t.atoms.bg_contrast_25,
       ]}>
       <SafeAreaView style={s.flex1}>
         <ScrollView style={styles.main}>
diff --git a/src/view/shell/desktop/Search.tsx b/src/view/shell/desktop/Search.tsx
index df49da55b..4a9483733 100644
--- a/src/view/shell/desktop/Search.tsx
+++ b/src/view/shell/desktop/Search.tsx
@@ -29,13 +29,63 @@ import {UserAvatar} from '#/view/com/util/UserAvatar'
 import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
 import {useModerationOpts} from '#/state/queries/preferences'
 
-export function SearchResultCard({
-  profile,
+export const MATCH_HANDLE =
+  /@?([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))/
+
+export function SearchLinkCard({
+  label,
+  to,
+  onPress,
   style,
+}: {
+  label: string
+  to?: string
+  onPress?: () => void
+  style?: ViewStyle
+}) {
+  const pal = usePalette('default')
+
+  const inner = (
+    <View
+      style={[pal.border, {paddingVertical: 16, paddingHorizontal: 12}, style]}>
+      <Text type="md" style={[pal.text]}>
+        {label}
+      </Text>
+    </View>
+  )
+
+  if (onPress) {
+    return (
+      <TouchableOpacity
+        onPress={onPress}
+        accessibilityLabel={label}
+        accessibilityHint="">
+        {inner}
+      </TouchableOpacity>
+    )
+  }
+
+  return (
+    <Link href={to} asAnchor anchorNoUnderline>
+      <View
+        style={[
+          pal.border,
+          {paddingVertical: 16, paddingHorizontal: 12},
+          style,
+        ]}>
+        <Text type="md" style={[pal.text]}>
+          {label}
+        </Text>
+      </View>
+    </Link>
+  )
+}
+
+export function SearchProfileCard({
+  profile,
   moderation,
 }: {
   profile: AppBskyActorDefs.ProfileViewBasic
-  style: ViewStyle
   moderation: ProfileModeration
 }) {
   const pal = usePalette('default')
@@ -50,9 +100,7 @@ export function SearchResultCard({
       <View
         style={[
           pal.border,
-          style,
           {
-            borderTopWidth: 1,
             flexDirection: 'row',
             alignItems: 'center',
             gap: 12,
@@ -147,6 +195,11 @@ export function DesktopSearch() {
     navigation.dispatch(StackActions.push('Search', {q: query}))
   }, [query, navigation, setSearchResults])
 
+  const queryMaybeHandle = React.useMemo(() => {
+    const match = MATCH_HANDLE.exec(query)
+    return match && match[1]
+  }, [query])
+
   return (
     <View style={[styles.container, pal.view]}>
       <View
@@ -198,22 +251,26 @@ export function DesktopSearch() {
             </View>
           ) : (
             <>
-              {searchResults.length ? (
-                searchResults.map((item, i) => (
-                  <SearchResultCard
-                    key={item.did}
-                    profile={item}
-                    moderation={moderateProfile(item, moderationOpts)}
-                    style={i === 0 ? {borderTopWidth: 0} : {}}
-                  />
-                ))
-              ) : (
-                <View>
-                  <Text style={[pal.textLight, styles.noResults]}>
-                    <Trans>No results found for {query}</Trans>
-                  </Text>
-                </View>
-              )}
+              <SearchLinkCard
+                label={_(msg`Search for "${query}"`)}
+                to={`/search?q=${encodeURIComponent(query)}`}
+                style={{borderBottomWidth: 1}}
+              />
+
+              {queryMaybeHandle ? (
+                <SearchLinkCard
+                  label={_(msg`Go to @${queryMaybeHandle}`)}
+                  to={`/profile/${queryMaybeHandle}`}
+                />
+              ) : null}
+
+              {searchResults.map(item => (
+                <SearchProfileCard
+                  key={item.did}
+                  profile={item}
+                  moderation={moderateProfile(item, moderationOpts)}
+                />
+              ))}
             </>
           )}
         </View>
diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx
index 51c03ae3d..5320aebfc 100644
--- a/src/view/shell/index.tsx
+++ b/src/view/shell/index.tsx
@@ -28,6 +28,7 @@ import {isAndroid} from 'platform/detection'
 import {useSession} from '#/state/session'
 import {useCloseAnyActiveElement} from '#/state/util'
 import * as notifications from 'lib/notifications/notifications'
+import {Outlet as PortalOutlet} from '#/components/Portal'
 
 function ShellInner() {
   const isDrawerOpen = useIsDrawerOpen()
@@ -94,6 +95,7 @@ function ShellInner() {
       </View>
       <Composer winHeight={winDim.height} />
       <ModalsContainer />
+      <PortalOutlet />
       <Lightbox />
     </>
   )
diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx
index 20bc0dff1..1ada883c9 100644
--- a/src/view/shell/index.web.tsx
+++ b/src/view/shell/index.web.tsx
@@ -15,6 +15,7 @@ import {useAuxClick} from 'lib/hooks/useAuxClick'
 import {t} from '@lingui/macro'
 import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell'
 import {useCloseAllActiveElements} from '#/state/util'
+import {Outlet as PortalOutlet} from '#/components/Portal'
 
 function ShellInner() {
   const isDrawerOpen = useIsDrawerOpen()
@@ -41,6 +42,7 @@ function ShellInner() {
       </View>
       <Composer winHeight={0} />
       <ModalsContainer />
+      <PortalOutlet />
       <Lightbox />
       {!isDesktop && isDrawerOpen && (
         <TouchableOpacity