about summary refs log tree commit diff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/Divider.tsx11
-rw-r--r--src/components/FeedCard.tsx2
-rw-r--r--src/components/ListCard.tsx12
-rw-r--r--src/components/Post/Embed/FeedEmbed.tsx43
-rw-r--r--src/components/Post/Embed/ListEmbed.tsx17
-rw-r--r--src/components/Post/Embed/index.tsx106
-rw-r--r--src/components/moderation/ContentHider.tsx13
7 files changed, 100 insertions, 104 deletions
diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx
index e4891aacb..ec7a7356a 100644
--- a/src/components/Divider.tsx
+++ b/src/components/Divider.tsx
@@ -1,18 +1,11 @@
 import {View} from 'react-native'
 
-import {atoms as a, flatten, useTheme, ViewStyleProp} from '#/alf'
+import {atoms as a, useTheme, type ViewStyleProp} from '#/alf'
 
 export function Divider({style}: ViewStyleProp) {
   const t = useTheme()
 
   return (
-    <View
-      style={[
-        a.w_full,
-        a.border_t,
-        t.atoms.border_contrast_low,
-        flatten(style),
-      ]}
-    />
+    <View style={[a.w_full, a.border_t, t.atoms.border_contrast_low, style]} />
   )
 }
diff --git a/src/components/FeedCard.tsx b/src/components/FeedCard.tsx
index f94692e5b..33905dacd 100644
--- a/src/components/FeedCard.tsx
+++ b/src/components/FeedCard.tsx
@@ -214,7 +214,7 @@ export function DescriptionPlaceholder() {
 export function Likes({count}: {count: number}) {
   const t = useTheme()
   return (
-    <Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
+    <Text style={[a.text_sm, t.atoms.text_contrast_medium, a.font_bold]}>
       <Trans>
         Liked by <Plural value={count || 0} one="# user" other="# users" />
       </Trans>
diff --git a/src/components/ListCard.tsx b/src/components/ListCard.tsx
index 30156ee0d..e34830ea9 100644
--- a/src/components/ListCard.tsx
+++ b/src/components/ListCard.tsx
@@ -1,10 +1,10 @@
 import React from 'react'
 import {View} from 'react-native'
 import {
-  AppBskyGraphDefs,
+  type AppBskyGraphDefs,
   AtUri,
   moderateUserList,
-  ModerationUI,
+  type ModerationUI,
 } from '@atproto/api'
 import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
@@ -22,10 +22,10 @@ import {
   Outer,
   SaveButton,
 } from '#/components/FeedCard'
-import {Link as InternalLink, LinkProps} from '#/components/Link'
+import {Link as InternalLink, type LinkProps} from '#/components/Link'
 import * as Hider from '#/components/moderation/Hider'
 import {Text} from '#/components/Typography'
-import * as bsky from '#/types/bsky'
+import type * as bsky from '#/types/bsky'
 
 /*
  * This component is based on `FeedCard` and is tightly coupled with that
@@ -50,7 +50,9 @@ type Props = {
   showPinButton?: boolean
 }
 
-export function Default(props: Props) {
+export function Default(
+  props: Props & Omit<LinkProps, 'to' | 'label' | 'children'>,
+) {
   const {view, showPinButton} = props
   const moderationOpts = useModerationOpts()
   const moderation = moderationOpts
diff --git a/src/components/Post/Embed/FeedEmbed.tsx b/src/components/Post/Embed/FeedEmbed.tsx
index fad4cd4d8..47d59e346 100644
--- a/src/components/Post/Embed/FeedEmbed.tsx
+++ b/src/components/Post/Embed/FeedEmbed.tsx
@@ -1,10 +1,9 @@
-import React from 'react'
-import {StyleSheet} from 'react-native'
+import {useMemo} from 'react'
 import {moderateFeedGenerator} from '@atproto/api'
 
-import {usePalette} from '#/lib/hooks/usePalette'
 import {useModerationOpts} from '#/state/preferences/moderation-opts'
-import {FeedSourceCard} from '#/view/com/feeds/FeedSourceCard'
+import {atoms as a, useTheme} from '#/alf'
+import * as FeedCard from '#/components/FeedCard'
 import {ContentHider} from '#/components/moderation/ContentHider'
 import {type EmbedType} from '#/types/bsky/post'
 import {type CommonProps} from './types'
@@ -14,13 +13,22 @@ export function FeedEmbed({
 }: CommonProps & {
   embed: EmbedType<'feed'>
 }) {
-  const pal = usePalette('default')
+  const t = useTheme()
   return (
-    <FeedSourceCard
-      feedUri={embed.view.uri}
-      style={[pal.view, pal.border, styles.customFeedOuter]}
-      showLikes
-    />
+    <FeedCard.Link
+      view={embed.view}
+      style={[a.border, t.atoms.border_contrast_medium, a.p_md, a.rounded_sm]}>
+      <FeedCard.Outer>
+        <FeedCard.Header>
+          <FeedCard.Avatar src={embed.view.avatar} />
+          <FeedCard.TitleAndByline
+            title={embed.view.displayName}
+            creator={embed.view.creator}
+          />
+        </FeedCard.Header>
+        <FeedCard.Likes count={embed.view.likeCount || 0} />
+      </FeedCard.Outer>
+    </FeedCard.Link>
   )
 }
 
@@ -30,23 +38,16 @@ export function ModeratedFeedEmbed({
   embed: EmbedType<'feed'>
 }) {
   const moderationOpts = useModerationOpts()
-  const moderation = React.useMemo(() => {
+  const moderation = useMemo(() => {
     return moderationOpts
       ? moderateFeedGenerator(embed.view, moderationOpts)
       : undefined
   }, [embed.view, moderationOpts])
   return (
-    <ContentHider modui={moderation?.ui('contentList')}>
+    <ContentHider
+      modui={moderation?.ui('contentList')}
+      childContainerStyle={[a.pt_xs]}>
       <FeedEmbed embed={embed} />
     </ContentHider>
   )
 }
-
-const styles = StyleSheet.create({
-  customFeedOuter: {
-    borderWidth: StyleSheet.hairlineWidth,
-    borderRadius: 8,
-    paddingHorizontal: 12,
-    paddingVertical: 12,
-  },
-})
diff --git a/src/components/Post/Embed/ListEmbed.tsx b/src/components/Post/Embed/ListEmbed.tsx
index 82685d271..c1450bdcf 100644
--- a/src/components/Post/Embed/ListEmbed.tsx
+++ b/src/components/Post/Embed/ListEmbed.tsx
@@ -1,5 +1,4 @@
-import React from 'react'
-import {View} from 'react-native'
+import {useMemo} from 'react'
 import {moderateUserList} from '@atproto/api'
 
 import {useModerationOpts} from '#/state/preferences/moderation-opts'
@@ -16,10 +15,10 @@ export function ListEmbed({
 }) {
   const t = useTheme()
   return (
-    <View
-      style={[a.border, t.atoms.border_contrast_medium, a.p_md, a.rounded_sm]}>
-      <ListCard.Default view={embed.view} />
-    </View>
+    <ListCard.Default
+      view={embed.view}
+      style={[a.border, t.atoms.border_contrast_medium, a.p_md, a.rounded_sm]}
+    />
   )
 }
 
@@ -29,13 +28,15 @@ export function ModeratedListEmbed({
   embed: EmbedType<'list'>
 }) {
   const moderationOpts = useModerationOpts()
-  const moderation = React.useMemo(() => {
+  const moderation = useMemo(() => {
     return moderationOpts
       ? moderateUserList(embed.view, moderationOpts)
       : undefined
   }, [embed.view, moderationOpts])
   return (
-    <ContentHider modui={moderation?.ui('contentList')}>
+    <ContentHider
+      modui={moderation?.ui('contentList')}
+      childContainerStyle={[a.pt_xs]}>
       <ListEmbed embed={embed} />
     </ContentHider>
   )
diff --git a/src/components/Post/Embed/index.tsx b/src/components/Post/Embed/index.tsx
index ace85dc98..9c5444b27 100644
--- a/src/components/Post/Embed/index.tsx
+++ b/src/components/Post/Embed/index.tsx
@@ -268,64 +268,60 @@ export function QuoteEmbed({
   const [hover, setHover] = React.useState(false)
   return (
     <View
-      onPointerEnter={() => {
-        setHover(true)
-      }}
-      onPointerLeave={() => {
-        setHover(false)
-      }}>
+      style={[a.mt_sm]}
+      onPointerEnter={() => setHover(true)}
+      onPointerLeave={() => setHover(false)}>
       <ContentHider
         modui={moderation?.ui('contentList')}
-        style={[
-          a.rounded_md,
-          a.p_md,
-          a.mt_sm,
-          a.border,
-          t.atoms.border_contrast_low,
-          style,
-        ]}
+        style={[a.rounded_md, a.border, t.atoms.border_contrast_low, style]}
+        activeStyle={[a.p_md, a.pt_sm]}
         childContainerStyle={[a.pt_sm]}>
-        <SubtleWebHover hover={hover} />
-        <Link
-          hoverStyle={{borderColor: pal.colors.borderLinkHover}}
-          href={itemHref}
-          title={itemTitle}
-          onBeforePress={onBeforePress}>
-          <View pointerEvents="none">
-            <PostMeta
-              author={quote.author}
-              moderation={moderation}
-              showAvatar
-              postHref={itemHref}
-              timestamp={quote.indexedAt}
-            />
-          </View>
-          {moderation ? (
-            <PostAlerts
-              modui={moderation.ui('contentView')}
-              style={[a.py_xs]}
-            />
-          ) : null}
-          {richText ? (
-            <RichText
-              value={richText}
-              style={a.text_md}
-              numberOfLines={20}
-              disableLinks
-            />
-          ) : null}
-          {quote.embed && (
-            <Embed
-              embed={quote.embed}
-              moderation={moderation}
-              isWithinQuote={parentIsWithinQuote ?? true}
-              // already within quote? override nested
-              allowNestedQuotes={
-                parentIsWithinQuote ? false : parentAllowNestedQuotes
-              }
-            />
-          )}
-        </Link>
+        {({active}) => (
+          <>
+            {!active && <SubtleWebHover hover={hover} style={[a.rounded_md]} />}
+            <Link
+              style={[!active && a.p_md]}
+              hoverStyle={{borderColor: pal.colors.borderLinkHover}}
+              href={itemHref}
+              title={itemTitle}
+              onBeforePress={onBeforePress}>
+              <View pointerEvents="none">
+                <PostMeta
+                  author={quote.author}
+                  moderation={moderation}
+                  showAvatar
+                  postHref={itemHref}
+                  timestamp={quote.indexedAt}
+                />
+              </View>
+              {moderation ? (
+                <PostAlerts
+                  modui={moderation.ui('contentView')}
+                  style={[a.py_xs]}
+                />
+              ) : null}
+              {richText ? (
+                <RichText
+                  value={richText}
+                  style={a.text_md}
+                  numberOfLines={20}
+                  disableLinks
+                />
+              ) : null}
+              {quote.embed && (
+                <Embed
+                  embed={quote.embed}
+                  moderation={moderation}
+                  isWithinQuote={parentIsWithinQuote ?? true}
+                  // already within quote? override nested
+                  allowNestedQuotes={
+                    parentIsWithinQuote ? false : parentAllowNestedQuotes
+                  }
+                />
+              )}
+            </Link>
+          </>
+        )}
       </ContentHider>
     </View>
   )
diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx
index 9e94a413c..549a1b9f0 100644
--- a/src/components/moderation/ContentHider.tsx
+++ b/src/components/moderation/ContentHider.tsx
@@ -23,20 +23,23 @@ export function ContentHider({
   modui,
   ignoreMute,
   style,
+  activeStyle,
   childContainerStyle,
   children,
-}: React.PropsWithChildren<{
+}: {
   testID?: string
   modui: ModerationUI | undefined
   ignoreMute?: boolean
   style?: StyleProp<ViewStyle>
+  activeStyle?: StyleProp<ViewStyle>
   childContainerStyle?: StyleProp<ViewStyle>
-}>) {
+  children?: React.ReactNode | ((props: {active: boolean}) => React.ReactNode)
+}) {
   const blur = modui?.blurs[0]
   if (!blur || (ignoreMute && isJustAMute(modui))) {
     return (
       <View testID={testID} style={style}>
-        {children}
+        {typeof children === 'function' ? children({active: false}) : children}
       </View>
     )
   }
@@ -44,9 +47,9 @@ export function ContentHider({
     <ContentHiderActive
       testID={testID}
       modui={modui}
-      style={style}
+      style={[style, activeStyle]}
       childContainerStyle={childContainerStyle}>
-      {children}
+      {typeof children === 'function' ? children({active: true}) : children}
     </ContentHiderActive>
   )
 }