about summary refs log tree commit diff
path: root/src/screens/Search/components/SearchHistory.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens/Search/components/SearchHistory.tsx')
-rw-r--r--src/screens/Search/components/SearchHistory.tsx169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/screens/Search/components/SearchHistory.tsx b/src/screens/Search/components/SearchHistory.tsx
new file mode 100644
index 000000000..5e62f2cd0
--- /dev/null
+++ b/src/screens/Search/components/SearchHistory.tsx
@@ -0,0 +1,169 @@
+import {Pressable, ScrollView, StyleSheet, View} from 'react-native'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {createHitslop, HITSLOP_10} from '#/lib/constants'
+import {makeProfileLink} from '#/lib/routes/links'
+import {sanitizeDisplayName} from '#/lib/strings/display-names'
+import {Link} from '#/view/com/util/Link'
+import {UserAvatar} from '#/view/com/util/UserAvatar'
+import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
+import {atoms as a, tokens, useBreakpoints, useTheme} from '#/alf'
+import {Button, ButtonIcon} from '#/components/Button'
+import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
+import * as Layout from '#/components/Layout'
+import {Text} from '#/components/Typography'
+import type * as bsky from '#/types/bsky'
+
+export function SearchHistory({
+  searchHistory,
+  selectedProfiles,
+  onItemClick,
+  onProfileClick,
+  onRemoveItemClick,
+  onRemoveProfileClick,
+}: {
+  searchHistory: string[]
+  selectedProfiles: bsky.profile.AnyProfileView[]
+  onItemClick: (item: string) => void
+  onProfileClick: (profile: bsky.profile.AnyProfileView) => void
+  onRemoveItemClick: (item: string) => void
+  onRemoveProfileClick: (profile: bsky.profile.AnyProfileView) => void
+}) {
+  const {gtMobile} = useBreakpoints()
+  const t = useTheme()
+  const {_} = useLingui()
+
+  return (
+    <Layout.Content
+      keyboardDismissMode="interactive"
+      keyboardShouldPersistTaps="handled">
+      <View style={[a.w_full, a.px_md]}>
+        {(searchHistory.length > 0 || selectedProfiles.length > 0) && (
+          <Text style={[a.text_md, a.font_bold, a.p_md]}>
+            <Trans>Recent Searches</Trans>
+          </Text>
+        )}
+        {selectedProfiles.length > 0 && (
+          <View
+            style={[
+              styles.selectedProfilesContainer,
+              !gtMobile && styles.selectedProfilesContainerMobile,
+            ]}>
+            <BlockDrawerGesture>
+              <ScrollView
+                horizontal
+                keyboardShouldPersistTaps="handled"
+                style={[
+                  a.flex_row,
+                  a.flex_nowrap,
+                  {marginHorizontal: tokens.space._2xl * -1},
+                ]}
+                contentContainerStyle={[a.px_2xl, a.border_0]}>
+                {selectedProfiles.slice(0, 5).map((profile, index) => (
+                  <View
+                    key={index}
+                    style={[
+                      styles.profileItem,
+                      !gtMobile && styles.profileItemMobile,
+                    ]}>
+                    <Link
+                      href={makeProfileLink(profile)}
+                      title={profile.handle}
+                      asAnchor
+                      anchorNoUnderline
+                      onBeforePress={() => onProfileClick(profile)}
+                      style={[a.align_center, a.w_full]}>
+                      <UserAvatar
+                        avatar={profile.avatar}
+                        type={profile.associated?.labeler ? 'labeler' : 'user'}
+                        size={60}
+                      />
+                      <Text
+                        emoji
+                        style={[a.text_xs, a.text_center, styles.profileName]}
+                        numberOfLines={1}>
+                        {sanitizeDisplayName(
+                          profile.displayName || profile.handle,
+                        )}
+                      </Text>
+                    </Link>
+                    <Pressable
+                      accessibilityRole="button"
+                      accessibilityLabel={_(msg`Remove profile`)}
+                      accessibilityHint={_(
+                        msg`Removes profile from search history`,
+                      )}
+                      onPress={() => onRemoveProfileClick(profile)}
+                      hitSlop={createHitslop(6)}
+                      style={styles.profileRemoveBtn}>
+                      <XIcon size="xs" style={t.atoms.text_contrast_low} />
+                    </Pressable>
+                  </View>
+                ))}
+              </ScrollView>
+            </BlockDrawerGesture>
+          </View>
+        )}
+        {searchHistory.length > 0 && (
+          <View style={[a.pl_md, a.pr_xs, a.mt_md]}>
+            {searchHistory.slice(0, 5).map((historyItem, index) => (
+              <View key={index} style={[a.flex_row, a.align_center, a.mt_xs]}>
+                <Pressable
+                  accessibilityRole="button"
+                  onPress={() => onItemClick(historyItem)}
+                  hitSlop={HITSLOP_10}
+                  style={[a.flex_1, a.py_md]}>
+                  <Text style={[a.text_md]}>{historyItem}</Text>
+                </Pressable>
+                <Button
+                  label={_(msg`Remove ${historyItem}`)}
+                  onPress={() => onRemoveItemClick(historyItem)}
+                  size="small"
+                  variant="ghost"
+                  color="secondary"
+                  shape="round">
+                  <ButtonIcon icon={XIcon} />
+                </Button>
+              </View>
+            ))}
+          </View>
+        )}
+      </View>
+    </Layout.Content>
+  )
+}
+
+const styles = StyleSheet.create({
+  selectedProfilesContainer: {
+    marginTop: 10,
+    paddingHorizontal: 12,
+    height: 80,
+  },
+  selectedProfilesContainerMobile: {
+    height: 100,
+  },
+  profileItem: {
+    alignItems: 'center',
+    marginRight: 15,
+    width: 78,
+  },
+  profileItemMobile: {
+    width: 70,
+  },
+  profileName: {
+    width: 78,
+    marginTop: 6,
+  },
+  profileRemoveBtn: {
+    position: 'absolute',
+    top: 0,
+    right: 5,
+    backgroundColor: 'white',
+    borderRadius: 10,
+    width: 18,
+    height: 18,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+})