about summary refs log tree commit diff
path: root/src/view/com/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/util')
-rw-r--r--src/view/com/util/ErrorBoundary.tsx3
-rw-r--r--src/view/com/util/Link.tsx9
-rw-r--r--src/view/com/util/moderation/ContentHider.tsx4
-rw-r--r--src/view/com/util/post-embeds/ExternalLinkEmbed.tsx44
-rw-r--r--src/view/com/util/post-embeds/QuoteEmbed.tsx24
-rw-r--r--src/view/com/util/post-embeds/index.tsx17
-rw-r--r--src/view/com/util/text/RichText.tsx34
7 files changed, 72 insertions, 63 deletions
diff --git a/src/view/com/util/ErrorBoundary.tsx b/src/view/com/util/ErrorBoundary.tsx
index 397588cfb..5ec1d0014 100644
--- a/src/view/com/util/ErrorBoundary.tsx
+++ b/src/view/com/util/ErrorBoundary.tsx
@@ -2,6 +2,7 @@ import React, {Component, ErrorInfo, ReactNode} from 'react'
 import {ErrorScreen} from './error/ErrorScreen'
 import {CenteredView} from './Views'
 import {t} from '@lingui/macro'
+import {logger} from '#/logger'
 
 interface Props {
   children?: ReactNode
@@ -23,7 +24,7 @@ export class ErrorBoundary extends Component<Props, State> {
   }
 
   public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
-    console.error('Uncaught error:', error, errorInfo)
+    logger.error(error, {errorInfo})
   }
 
   public render() {
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index 4f898767d..db26258d6 100644
--- a/src/view/com/util/Link.tsx
+++ b/src/view/com/util/Link.tsx
@@ -306,6 +306,8 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
   )
 })
 
+const EXEMPT_PATHS = ['/robots.txt', '/security.txt', '/.well-known/']
+
 // NOTE
 // we can't use the onPress given by useLinkProps because it will
 // match most paths to the HomeTab routes while we actually want to
@@ -350,7 +352,12 @@ function onPressInner(
 
   if (shouldHandle) {
     href = convertBskyAppUrlIfNeeded(href)
-    if (newTab || href.startsWith('http') || href.startsWith('mailto')) {
+    if (
+      newTab ||
+      href.startsWith('http') ||
+      href.startsWith('mailto') ||
+      EXEMPT_PATHS.some(path => href.startsWith(path))
+    ) {
       openLink(href)
     } else {
       closeModal() // close any active modals
diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx
index 249c556ec..b3a563116 100644
--- a/src/view/com/util/moderation/ContentHider.tsx
+++ b/src/view/com/util/moderation/ContentHider.tsx
@@ -94,7 +94,7 @@ export function ContentHider({
             <ShieldExclamation size={18} style={pal.textLight} />
           )}
         </Pressable>
-        <Text type="md" style={pal.text}>
+        <Text type="md" style={[pal.text, {flex: 1}]} numberOfLines={2}>
           {desc.name}
         </Text>
         <View style={styles.showBtn}>
@@ -131,7 +131,7 @@ const styles = StyleSheet.create({
   cover: {
     flexDirection: 'row',
     alignItems: 'center',
-    gap: 4,
+    gap: 6,
     borderRadius: 8,
     marginTop: 4,
     paddingVertical: 14,
diff --git a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx
index af62aa2b3..aaa98a41f 100644
--- a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx
+++ b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx
@@ -29,22 +29,13 @@ export const ExternalLinkEmbed = ({
   }, [link.uri, externalEmbedPrefs])
 
   return (
-    <View style={{flexDirection: 'column'}}>
+    <View style={styles.container}>
       {link.thumb && !embedPlayerParams ? (
-        <View
-          style={{
-            borderTopLeftRadius: 6,
-            borderTopRightRadius: 6,
-            width: '100%',
-            height: isMobile ? 200 : 300,
-            overflow: 'hidden',
-          }}>
-          <Image
-            style={styles.extImage}
-            source={{uri: link.thumb}}
-            accessibilityIgnoresInvertColors
-          />
-        </View>
+        <Image
+          style={{aspectRatio: 1.91}}
+          source={{uri: link.thumb}}
+          accessibilityIgnoresInvertColors
+        />
       ) : undefined}
       {(embedPlayerParams?.isGif && (
         <ExternalGifEmbed link={link} params={embedPlayerParams} />
@@ -52,12 +43,7 @@ export const ExternalLinkEmbed = ({
         (embedPlayerParams && (
           <ExternalPlayer link={link} params={embedPlayerParams} />
         ))}
-      <View
-        style={{
-          paddingHorizontal: isMobile ? 10 : 14,
-          paddingTop: 8,
-          paddingBottom: 10,
-        }}>
+      <View style={[styles.info, {paddingHorizontal: isMobile ? 10 : 14}]}>
         <Text
           type="sm"
           numberOfLines={1}
@@ -65,14 +51,14 @@ export const ExternalLinkEmbed = ({
           {toNiceDomain(link.uri)}
         </Text>
         {!embedPlayerParams?.isGif && (
-          <Text type="lg-bold" numberOfLines={4} style={[pal.text]}>
+          <Text type="lg-bold" numberOfLines={3} style={[pal.text]}>
             {link.title || link.uri}
           </Text>
         )}
         {link.description && !embedPlayerParams?.hideDetails ? (
           <Text
             type="md"
-            numberOfLines={4}
+            numberOfLines={link.thumb ? 2 : 4}
             style={[pal.text, styles.extDescription]}>
             {link.description}
           </Text>
@@ -83,8 +69,16 @@ export const ExternalLinkEmbed = ({
 }
 
 const styles = StyleSheet.create({
-  extImage: {
-    flex: 1,
+  container: {
+    flexDirection: 'column',
+    borderRadius: 6,
+    overflow: 'hidden',
+  },
+  info: {
+    width: '100%',
+    bottom: 0,
+    paddingTop: 8,
+    paddingBottom: 10,
   },
   extUri: {
     marginTop: 2,
diff --git a/src/view/com/util/post-embeds/QuoteEmbed.tsx b/src/view/com/util/post-embeds/QuoteEmbed.tsx
index e5fe44c4d..256817bba 100644
--- a/src/view/com/util/post-embeds/QuoteEmbed.tsx
+++ b/src/view/com/util/post-embeds/QuoteEmbed.tsx
@@ -7,6 +7,7 @@ import {
   AppBskyEmbedRecordWithMedia,
   ModerationUI,
   AppBskyEmbedExternal,
+  RichText as RichTextAPI,
 } from '@atproto/api'
 import {AtUri} from '@atproto/api'
 import {PostMeta} from '../PostMeta'
@@ -19,6 +20,7 @@ import {PostAlerts} from '../moderation/PostAlerts'
 import {makeProfileLink} from 'lib/routes/links'
 import {InfoCircleIcon} from 'lib/icons'
 import {Trans} from '@lingui/macro'
+import {RichText} from 'view/com/util/text/RichText'
 
 export function MaybeQuoteEmbed({
   embed,
@@ -43,6 +45,7 @@ export function MaybeQuoteEmbed({
           uri: embed.record.uri,
           indexedAt: embed.record.indexedAt,
           text: embed.record.value.text,
+          facets: embed.record.value.facets,
           embeds: embed.record.embeds,
         }}
         moderation={moderation}
@@ -84,9 +87,12 @@ export function QuoteEmbed({
   const itemUrip = new AtUri(quote.uri)
   const itemHref = makeProfileLink(quote.author, 'post', itemUrip.rkey)
   const itemTitle = `Post by ${quote.author.handle}`
-  const isEmpty = React.useMemo(
-    () => quote.text.trim().length === 0,
-    [quote.text],
+  const richText = React.useMemo(
+    () =>
+      quote.text.trim()
+        ? new RichTextAPI({text: quote.text, facets: quote.facets})
+        : undefined,
+    [quote.text, quote.facets],
   )
   const embed = React.useMemo(() => {
     const e = quote.embeds?.[0]
@@ -117,10 +123,14 @@ export function QuoteEmbed({
       {moderation ? (
         <PostAlerts moderation={moderation} style={styles.alert} />
       ) : null}
-      {!isEmpty ? (
-        <Text type="post-text" style={pal.text} numberOfLines={20}>
-          {quote.text}
-        </Text>
+      {richText ? (
+        <RichText
+          richText={richText}
+          type="post-text"
+          style={pal.text}
+          numberOfLines={20}
+          noLinks
+        />
       ) : null}
       {embed && <PostEmbeds embed={embed} moderation={{}} />}
     </Link>
diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx
index 00a102e7b..6f168a293 100644
--- a/src/view/com/util/post-embeds/index.tsx
+++ b/src/view/com/util/post-embeds/index.tsx
@@ -22,7 +22,6 @@ import {Link} from '../Link'
 import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
 import {useLightboxControls, ImagesLightbox} from '#/state/lightbox'
 import {usePalette} from 'lib/hooks/usePalette'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {ExternalLinkEmbed} from './ExternalLinkEmbed'
 import {MaybeQuoteEmbed} from './QuoteEmbed'
 import {AutoSizedImage} from '../images/AutoSizedImage'
@@ -51,7 +50,6 @@ export function PostEmbeds({
 }) {
   const pal = usePalette('default')
   const {openLightbox} = useLightboxControls()
-  const {isMobile} = useWebMediaQueries()
 
   // quote post with media
   // =
@@ -129,10 +127,7 @@ export function PostEmbeds({
               dimensionsHint={aspectRatio}
               onPress={() => _openLightbox(0)}
               onPressIn={() => onPressIn(0)}
-              style={[
-                styles.singleImage,
-                isMobile && styles.singleImageMobile,
-              ]}>
+              style={[styles.singleImage]}>
               {alt === '' ? null : (
                 <View style={styles.altContainer}>
                   <Text style={styles.alt} accessible={false}>
@@ -151,11 +146,7 @@ export function PostEmbeds({
             images={embed.images}
             onPress={_openLightbox}
             onPressIn={onPressIn}
-            style={
-              embed.images.length === 1
-                ? [styles.singleImage, isMobile && styles.singleImageMobile]
-                : undefined
-            }
+            style={embed.images.length === 1 ? [styles.singleImage] : undefined}
           />
         </View>
       )
@@ -188,10 +179,6 @@ const styles = StyleSheet.create({
   },
   singleImage: {
     borderRadius: 8,
-    maxHeight: 1000,
-  },
-  singleImageMobile: {
-    maxHeight: 500,
   },
   extOuter: {
     borderWidth: 1,
diff --git a/src/view/com/util/text/RichText.tsx b/src/view/com/util/text/RichText.tsx
index 99062e848..da473d929 100644
--- a/src/view/com/util/text/RichText.tsx
+++ b/src/view/com/util/text/RichText.tsx
@@ -17,6 +17,7 @@ export function RichText({
   lineHeight = 1.2,
   style,
   numberOfLines,
+  noLinks,
 }: {
   testID?: string
   type?: TypographyVariant
@@ -24,6 +25,7 @@ export function RichText({
   lineHeight?: number
   style?: StyleProp<TextStyle>
   numberOfLines?: number
+  noLinks?: boolean
 }) {
   const theme = useTheme()
   const pal = usePalette('default')
@@ -70,7 +72,11 @@ export function RichText({
   for (const segment of richText.segments()) {
     const link = segment.link
     const mention = segment.mention
-    if (mention && AppBskyRichtextFacet.validateMention(mention).success) {
+    if (
+      !noLinks &&
+      mention &&
+      AppBskyRichtextFacet.validateMention(mention).success
+    ) {
       els.push(
         <TextLink
           key={key}
@@ -82,17 +88,21 @@ export function RichText({
         />,
       )
     } else if (link && AppBskyRichtextFacet.validateLink(link).success) {
-      els.push(
-        <TextLink
-          key={key}
-          type={type}
-          text={toShortUrl(segment.text)}
-          href={link.uri}
-          style={[style, lineHeightStyle, pal.link, {pointerEvents: 'auto'}]}
-          dataSet={WORD_WRAP}
-          warnOnMismatchingLabel
-        />,
-      )
+      if (noLinks) {
+        els.push(toShortUrl(segment.text))
+      } else {
+        els.push(
+          <TextLink
+            key={key}
+            type={type}
+            text={toShortUrl(segment.text)}
+            href={link.uri}
+            style={[style, lineHeightStyle, pal.link, {pointerEvents: 'auto'}]}
+            dataSet={WORD_WRAP}
+            warnOnMismatchingLabel
+          />,
+        )
+      }
     } else {
       els.push(segment.text)
     }