zio/stable
Paul Frazee 2023-10-30 19:26:23 -07:00
commit 40752982da
6 changed files with 64 additions and 5 deletions

View File

@ -147,3 +147,4 @@ export const HITSLOP_10 = createHitslop(10)
export const HITSLOP_20 = createHitslop(20) export const HITSLOP_20 = createHitslop(20)
export const HITSLOP_30 = createHitslop(30) export const HITSLOP_30 = createHitslop(30)
export const BACK_HITSLOP = HITSLOP_30 export const BACK_HITSLOP = HITSLOP_30
export const MAX_POST_LINES = 25

View File

@ -32,3 +32,8 @@ export function toHashCode(str: string, seed = 0): number {
return 4294967296 * (2097151 & h2) + (h1 >>> 0) return 4294967296 * (2097151 & h2) + (h1 >>> 0)
} }
export function countLines(str: string | undefined): number {
if (!str) return 0
return str.match(/\n/g)?.length ?? 0
}

View File

@ -8,7 +8,7 @@ import {
FontAwesomeIconStyle, FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome' } from '@fortawesome/react-native-fontawesome'
import {PostThreadItemModel} from 'state/models/content/post-thread-item' 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 {RichText} from '../util/text/RichText'
import {Text} from '../util/text/Text' import {Text} from '../util/text/Text'
import {PostDropdownBtn} from '../util/forms/PostDropdownBtn' import {PostDropdownBtn} from '../util/forms/PostDropdownBtn'
@ -18,7 +18,7 @@ import {s} from 'lib/styles'
import {niceDate} from 'lib/strings/time' import {niceDate} from 'lib/strings/time'
import {sanitizeDisplayName} from 'lib/strings/display-names' import {sanitizeDisplayName} from 'lib/strings/display-names'
import {sanitizeHandle} from 'lib/strings/handles' 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 {isEmbedByEmbedder} from 'lib/embeds'
import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers' import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers'
import {useStores} from 'state/index' import {useStores} from 'state/index'
@ -35,6 +35,7 @@ import {formatCount} from '../util/numeric/format'
import {TimeElapsed} from 'view/com/util/TimeElapsed' import {TimeElapsed} from 'view/com/util/TimeElapsed'
import {makeProfileLink} from 'lib/routes/links' import {makeProfileLink} from 'lib/routes/links'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {MAX_POST_LINES} from 'lib/constants'
export const PostThreadItem = observer(function PostThreadItem({ export const PostThreadItem = observer(function PostThreadItem({
item, item,
@ -50,6 +51,9 @@ export const PostThreadItem = observer(function PostThreadItem({
const pal = usePalette('default') const pal = usePalette('default')
const store = useStores() const store = useStores()
const [deleted, setDeleted] = React.useState(false) const [deleted, setDeleted] = React.useState(false)
const [limitLines, setLimitLines] = React.useState(
countLines(item.richText?.text) >= MAX_POST_LINES,
)
const styles = useStyles() const styles = useStyles()
const record = item.postRecord const record = item.postRecord
const hasEngagement = item.post.likeCount || item.post.repostCount const hasEngagement = item.post.likeCount || item.post.repostCount
@ -151,6 +155,10 @@ export const PostThreadItem = observer(function PostThreadItem({
) )
}, [item, store]) }, [item, store])
const onPressShowMore = React.useCallback(() => {
setLimitLines(false)
}, [setLimitLines])
if (!record) { if (!record) {
return <ErrorMessage message="Invalid or unsupported post record" /> return <ErrorMessage message="Invalid or unsupported post record" />
} }
@ -489,9 +497,18 @@ export const PostThreadItem = observer(function PostThreadItem({
richText={item.richText} richText={item.richText}
style={[pal.text, s.flex1]} style={[pal.text, s.flex1]}
lineHeight={1.3} lineHeight={1.3}
numberOfLines={limitLines ? MAX_POST_LINES : undefined}
/> />
</View> </View>
) : undefined} ) : undefined}
{limitLines ? (
<TextLink
text="Show More"
style={pal.link}
onPress={onPressShowMore}
href="#"
/>
) : undefined}
{item.post.embed && ( {item.post.embed && (
<ContentHider <ContentHider
style={styles.contentHider} style={styles.contentHider}

View File

@ -14,7 +14,7 @@ import {AtUri} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {PostThreadModel} from 'state/models/content/post-thread' import {PostThreadModel} from 'state/models/content/post-thread'
import {PostThreadItemModel} from 'state/models/content/post-thread-item' 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 {UserInfoText} from '../util/UserInfoText'
import {PostMeta} from '../util/PostMeta' import {PostMeta} from '../util/PostMeta'
import {PostEmbeds} from '../util/post-embeds' import {PostEmbeds} from '../util/post-embeds'
@ -30,6 +30,8 @@ import {s, colors} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {getTranslatorLink} from '../../../locale/helpers' import {getTranslatorLink} from '../../../locale/helpers'
import {makeProfileLink} from 'lib/routes/links' 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({ export const Post = observer(function PostImpl({
view, view,
@ -103,7 +105,9 @@ const PostLoaded = observer(function PostLoadedImpl({
}) { }) {
const pal = usePalette('default') const pal = usePalette('default')
const store = useStores() const store = useStores()
const [limitLines, setLimitLines] = React.useState(
countLines(item.richText?.text) >= MAX_POST_LINES,
)
const itemUri = item.post.uri const itemUri = item.post.uri
const itemCid = item.post.cid const itemCid = item.post.cid
const itemUrip = new AtUri(item.post.uri) const itemUrip = new AtUri(item.post.uri)
@ -182,6 +186,10 @@ const PostLoaded = observer(function PostLoadedImpl({
) )
}, [item, setDeleted, store]) }, [item, setDeleted, store])
const onPressShowMore = React.useCallback(() => {
setLimitLines(false)
}, [setLimitLines])
return ( return (
<Link href={itemHref} style={[styles.outer, pal.view, pal.border, style]}> <Link href={itemHref} style={[styles.outer, pal.view, pal.border, style]}>
{showReplyLine && <View style={styles.replyLine} />} {showReplyLine && <View style={styles.replyLine} />}
@ -239,10 +247,19 @@ const PostLoaded = observer(function PostLoadedImpl({
type="post-text" type="post-text"
richText={item.richText} richText={item.richText}
lineHeight={1.3} lineHeight={1.3}
numberOfLines={limitLines ? MAX_POST_LINES : undefined}
style={s.flex1} style={s.flex1}
/> />
</View> </View>
) : undefined} ) : undefined}
{limitLines ? (
<TextLink
text="Show More"
style={pal.link}
onPress={onPressShowMore}
href="#"
/>
) : undefined}
{item.post.embed ? ( {item.post.embed ? (
<ContentHider <ContentHider
moderation={item.moderation.embed} moderation={item.moderation.embed}

View File

@ -9,7 +9,7 @@ import {
} from '@fortawesome/react-native-fontawesome' } from '@fortawesome/react-native-fontawesome'
import {PostsFeedItemModel} from 'state/models/feeds/post' import {PostsFeedItemModel} from 'state/models/feeds/post'
import {FeedSourceInfo} from 'lib/api/feed/types' 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 {Text} from '../util/text/Text'
import {UserInfoText} from '../util/UserInfoText' import {UserInfoText} from '../util/UserInfoText'
import {PostMeta} from '../util/PostMeta' import {PostMeta} from '../util/PostMeta'
@ -30,6 +30,8 @@ import {sanitizeHandle} from 'lib/strings/handles'
import {getTranslatorLink} from '../../../locale/helpers' import {getTranslatorLink} from '../../../locale/helpers'
import {makeProfileLink} from 'lib/routes/links' import {makeProfileLink} from 'lib/routes/links'
import {isEmbedByEmbedder} from 'lib/embeds' import {isEmbedByEmbedder} from 'lib/embeds'
import {MAX_POST_LINES} from 'lib/constants'
import {countLines} from 'lib/strings/helpers'
export const FeedItem = observer(function FeedItemImpl({ export const FeedItem = observer(function FeedItemImpl({
item, item,
@ -49,6 +51,9 @@ export const FeedItem = observer(function FeedItemImpl({
const pal = usePalette('default') const pal = usePalette('default')
const {track} = useAnalytics() const {track} = useAnalytics()
const [deleted, setDeleted] = useState(false) const [deleted, setDeleted] = useState(false)
const [limitLines, setLimitLines] = useState(
countLines(item.richText?.text) >= MAX_POST_LINES,
)
const record = item.postRecord const record = item.postRecord
const itemUri = item.post.uri const itemUri = item.post.uri
const itemCid = item.post.cid const itemCid = item.post.cid
@ -136,6 +141,10 @@ export const FeedItem = observer(function FeedItemImpl({
) )
}, [track, item, setDeleted, store]) }, [track, item, setDeleted, store])
const onPressShowMore = React.useCallback(() => {
setLimitLines(false)
}, [setLimitLines])
const outerStyles = [ const outerStyles = [
styles.outer, styles.outer,
pal.view, pal.view,
@ -307,10 +316,19 @@ export const FeedItem = observer(function FeedItemImpl({
type="post-text" type="post-text"
richText={item.richText} richText={item.richText}
lineHeight={1.3} lineHeight={1.3}
numberOfLines={limitLines ? MAX_POST_LINES : undefined}
style={s.flex1} style={s.flex1}
/> />
</View> </View>
) : undefined} ) : undefined}
{limitLines ? (
<TextLink
text="Show More"
style={pal.link}
onPress={onPressShowMore}
href="#"
/>
) : undefined}
{item.post.embed ? ( {item.post.embed ? (
<ContentHider <ContentHider
testID="contentHider-embed" testID="contentHider-embed"

View File

@ -52,6 +52,7 @@ export function RichText({
testID={testID} testID={testID}
type={type} type={type}
style={[style, pal.text, lineHeightStyle]} style={[style, pal.text, lineHeightStyle]}
numberOfLines={numberOfLines}
// @ts-ignore web only -prf // @ts-ignore web only -prf
dataSet={WORD_WRAP}> dataSet={WORD_WRAP}>
{text} {text}