about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/constants.ts1
-rw-r--r--src/lib/strings/helpers.ts5
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx21
-rw-r--r--src/view/com/post/Post.tsx21
-rw-r--r--src/view/com/posts/FeedItem.tsx20
-rw-r--r--src/view/com/util/text/RichText.tsx1
6 files changed, 64 insertions, 5 deletions
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 81a6d4e77..472b59d76 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -147,3 +147,4 @@ export const HITSLOP_10 = createHitslop(10)
 export const HITSLOP_20 = createHitslop(20)
 export const HITSLOP_30 = createHitslop(30)
 export const BACK_HITSLOP = HITSLOP_30
+export const MAX_POST_LINES = 25
diff --git a/src/lib/strings/helpers.ts b/src/lib/strings/helpers.ts
index ef93a366f..381ae32f3 100644
--- a/src/lib/strings/helpers.ts
+++ b/src/lib/strings/helpers.ts
@@ -32,3 +32,8 @@ export function toHashCode(str: string, seed = 0): number {
 
   return 4294967296 * (2097151 & h2) + (h1 >>> 0)
 }
+
+export function countLines(str: string | undefined): number {
+  if (!str) return 0
+  return str.match(/\n/g)?.length ?? 0
+}
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 75d756d61..8976a7e2c 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -8,7 +8,7 @@ import {
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
 import {PostThreadItemModel} from 'state/models/content/post-thread-item'
-import {Link} from '../util/Link'
+import {Link, TextLink} from '../util/Link'
 import {RichText} from '../util/text/RichText'
 import {Text} from '../util/text/Text'
 import {PostDropdownBtn} from '../util/forms/PostDropdownBtn'
@@ -18,7 +18,7 @@ import {s} from 'lib/styles'
 import {niceDate} from 'lib/strings/time'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
-import {pluralize} from 'lib/strings/helpers'
+import {countLines, pluralize} from 'lib/strings/helpers'
 import {isEmbedByEmbedder} from 'lib/embeds'
 import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers'
 import {useStores} from 'state/index'
@@ -35,6 +35,7 @@ import {formatCount} from '../util/numeric/format'
 import {TimeElapsed} from 'view/com/util/TimeElapsed'
 import {makeProfileLink} from 'lib/routes/links'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {MAX_POST_LINES} from 'lib/constants'
 
 export const PostThreadItem = observer(function PostThreadItem({
   item,
@@ -50,6 +51,9 @@ export const PostThreadItem = observer(function PostThreadItem({
   const pal = usePalette('default')
   const store = useStores()
   const [deleted, setDeleted] = React.useState(false)
+  const [limitLines, setLimitLines] = React.useState(
+    countLines(item.richText?.text) >= MAX_POST_LINES,
+  )
   const styles = useStyles()
   const record = item.postRecord
   const hasEngagement = item.post.likeCount || item.post.repostCount
@@ -151,6 +155,10 @@ export const PostThreadItem = observer(function PostThreadItem({
     )
   }, [item, store])
 
+  const onPressShowMore = React.useCallback(() => {
+    setLimitLines(false)
+  }, [setLimitLines])
+
   if (!record) {
     return <ErrorMessage message="Invalid or unsupported post record" />
   }
@@ -489,9 +497,18 @@ export const PostThreadItem = observer(function PostThreadItem({
                     richText={item.richText}
                     style={[pal.text, s.flex1]}
                     lineHeight={1.3}
+                    numberOfLines={limitLines ? MAX_POST_LINES : undefined}
                   />
                 </View>
               ) : undefined}
+              {limitLines ? (
+                <TextLink
+                  text="Show More"
+                  style={pal.link}
+                  onPress={onPressShowMore}
+                  href="#"
+                />
+              ) : undefined}
               {item.post.embed && (
                 <ContentHider
                   style={styles.contentHider}
diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx
index d5191cf4e..e3c948e5d 100644
--- a/src/view/com/post/Post.tsx
+++ b/src/view/com/post/Post.tsx
@@ -14,7 +14,7 @@ import {AtUri} from '@atproto/api'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {PostThreadModel} from 'state/models/content/post-thread'
 import {PostThreadItemModel} from 'state/models/content/post-thread-item'
-import {Link} from '../util/Link'
+import {Link, TextLink} from '../util/Link'
 import {UserInfoText} from '../util/UserInfoText'
 import {PostMeta} from '../util/PostMeta'
 import {PostEmbeds} from '../util/post-embeds'
@@ -30,6 +30,8 @@ import {s, colors} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {getTranslatorLink} from '../../../locale/helpers'
 import {makeProfileLink} from 'lib/routes/links'
+import {MAX_POST_LINES} from 'lib/constants'
+import {countLines} from 'lib/strings/helpers'
 
 export const Post = observer(function PostImpl({
   view,
@@ -103,7 +105,9 @@ const PostLoaded = observer(function PostLoadedImpl({
 }) {
   const pal = usePalette('default')
   const store = useStores()
-
+  const [limitLines, setLimitLines] = React.useState(
+    countLines(item.richText?.text) >= MAX_POST_LINES,
+  )
   const itemUri = item.post.uri
   const itemCid = item.post.cid
   const itemUrip = new AtUri(item.post.uri)
@@ -182,6 +186,10 @@ const PostLoaded = observer(function PostLoadedImpl({
     )
   }, [item, setDeleted, store])
 
+  const onPressShowMore = React.useCallback(() => {
+    setLimitLines(false)
+  }, [setLimitLines])
+
   return (
     <Link href={itemHref} style={[styles.outer, pal.view, pal.border, style]}>
       {showReplyLine && <View style={styles.replyLine} />}
@@ -239,10 +247,19 @@ const PostLoaded = observer(function PostLoadedImpl({
                   type="post-text"
                   richText={item.richText}
                   lineHeight={1.3}
+                  numberOfLines={limitLines ? MAX_POST_LINES : undefined}
                   style={s.flex1}
                 />
               </View>
             ) : undefined}
+            {limitLines ? (
+              <TextLink
+                text="Show More"
+                style={pal.link}
+                onPress={onPressShowMore}
+                href="#"
+              />
+            ) : undefined}
             {item.post.embed ? (
               <ContentHider
                 moderation={item.moderation.embed}
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index 6aac450ff..441621638 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -9,7 +9,7 @@ import {
 } from '@fortawesome/react-native-fontawesome'
 import {PostsFeedItemModel} from 'state/models/feeds/post'
 import {FeedSourceInfo} from 'lib/api/feed/types'
-import {Link, TextLinkOnWebOnly} from '../util/Link'
+import {Link, TextLinkOnWebOnly, TextLink} from '../util/Link'
 import {Text} from '../util/text/Text'
 import {UserInfoText} from '../util/UserInfoText'
 import {PostMeta} from '../util/PostMeta'
@@ -30,6 +30,8 @@ import {sanitizeHandle} from 'lib/strings/handles'
 import {getTranslatorLink} from '../../../locale/helpers'
 import {makeProfileLink} from 'lib/routes/links'
 import {isEmbedByEmbedder} from 'lib/embeds'
+import {MAX_POST_LINES} from 'lib/constants'
+import {countLines} from 'lib/strings/helpers'
 
 export const FeedItem = observer(function FeedItemImpl({
   item,
@@ -49,6 +51,9 @@ export const FeedItem = observer(function FeedItemImpl({
   const pal = usePalette('default')
   const {track} = useAnalytics()
   const [deleted, setDeleted] = useState(false)
+  const [limitLines, setLimitLines] = useState(
+    countLines(item.richText?.text) >= MAX_POST_LINES,
+  )
   const record = item.postRecord
   const itemUri = item.post.uri
   const itemCid = item.post.cid
@@ -136,6 +141,10 @@ export const FeedItem = observer(function FeedItemImpl({
     )
   }, [track, item, setDeleted, store])
 
+  const onPressShowMore = React.useCallback(() => {
+    setLimitLines(false)
+  }, [setLimitLines])
+
   const outerStyles = [
     styles.outer,
     pal.view,
@@ -307,10 +316,19 @@ export const FeedItem = observer(function FeedItemImpl({
                   type="post-text"
                   richText={item.richText}
                   lineHeight={1.3}
+                  numberOfLines={limitLines ? MAX_POST_LINES : undefined}
                   style={s.flex1}
                 />
               </View>
             ) : undefined}
+            {limitLines ? (
+              <TextLink
+                text="Show More"
+                style={pal.link}
+                onPress={onPressShowMore}
+                href="#"
+              />
+            ) : undefined}
             {item.post.embed ? (
               <ContentHider
                 testID="contentHider-embed"
diff --git a/src/view/com/util/text/RichText.tsx b/src/view/com/util/text/RichText.tsx
index 34c201829..b414baed9 100644
--- a/src/view/com/util/text/RichText.tsx
+++ b/src/view/com/util/text/RichText.tsx
@@ -52,6 +52,7 @@ export function RichText({
         testID={testID}
         type={type}
         style={[style, pal.text, lineHeightStyle]}
+        numberOfLines={numberOfLines}
         // @ts-ignore web only -prf
         dataSet={WORD_WRAP}>
         {text}