diff --git a/App.tsx b/App.tsx
index da6e0493..6fa4a7e6 100644
--- a/App.tsx
+++ b/App.tsx
@@ -10,14 +10,13 @@ import { persistor, store } from '@root/store'
import { resetLocal } from '@root/utils/slices/instancesSlice'
import ThemeManager from '@utils/styles/ThemeManager'
-// if (__DEV__) {
-// const whyDidYouRender = require('@welldone-software/why-did-you-render')
-// whyDidYouRender(React, {
-// trackAllPureComponents: true,
-// trackHooks: true,
-// hotReloadBufferMs: 1000
-// })
-// }
+if (__DEV__) {
+ const whyDidYouRender = require('@welldone-software/why-did-you-render')
+ whyDidYouRender(React, {
+ trackHooks: true,
+ hotReloadBufferMs: 1000
+ })
+}
const queryClient = new QueryClient()
diff --git a/src/components/ParseContent.tsx b/src/components/ParseContent.tsx
index ed50ab75..3bdeb751 100644
--- a/src/components/ParseContent.tsx
+++ b/src/components/ParseContent.tsx
@@ -1,4 +1,5 @@
-import React, { useCallback, useState } from 'react'
+import { LinearGradient } from 'expo-linear-gradient'
+import React, { useCallback, useMemo, useState } from 'react'
import { Pressable, Text, View } from 'react-native'
import HTMLView from 'react-native-htmlview'
import { useNavigation } from '@react-navigation/native'
@@ -6,8 +7,8 @@ import Emojis from '@components/Timelines/Timeline/Shared/Emojis'
import { useTheme } from '@utils/styles/ThemeManager'
import { Feather } from '@expo/vector-icons'
import { StyleConstants } from '@utils/styles/constants'
-import { LinearGradient } from 'expo-linear-gradient'
import openLink from '@root/utils/openLink'
+import layoutAnimation from '@root/utils/styles/layoutAnimation'
// Prevent going to the same hashtag multiple times
const renderNode = ({
@@ -96,7 +97,7 @@ const renderNode = ({
} else {
if (node.name === 'p') {
if (!node.children.length) {
- return // bug when the tag is empty
+ return // bug when the tag is empty
}
}
}
@@ -109,6 +110,7 @@ export interface Props {
mentions?: Mastodon.Mention[]
showFullLink?: boolean
numberOfLines?: number
+ expandHint?: string
}
const ParseContent: React.FC = ({
@@ -117,7 +119,8 @@ const ParseContent: React.FC = ({
emojis,
mentions,
showFullLink = false,
- numberOfLines = 10
+ numberOfLines = 10,
+ expandHint = '全文'
}) => {
const navigation = useNavigation()
const { theme } = useTheme()
@@ -136,55 +139,76 @@ const ParseContent: React.FC = ({
[]
)
const textComponent = useCallback(({ children }) => {
- return emojis && children ? (
-
- ) : (
- {children}
- )
+ if (children) {
+ return emojis ? (
+
+ ) : (
+ {children}
+ )
+ } else {
+ return null
+ }
}, [])
const rootComponent = useCallback(({ children }) => {
- const { theme } = useTheme()
- const [textLoaded, setTextLoaded] = useState(false)
- const [totalLines, setTotalLines] = useState()
- const [lineHeight, setLineHeight] = useState()
- const [shownLines, setShownLines] = useState(numberOfLines)
+ // layoutAnimation()
+ const lineHeight = StyleConstants.Font.LineHeight[size]
+
+ const [heightOriginal, setHeightOriginal] = useState()
+ const [heightTruncated, setHeightTruncated] = useState()
+ const [allowExpand, setAllowExpand] = useState(false)
+ const [showAllText, setShowAllText] = useState(false)
+
+ const calNumberOfLines = useMemo(() => {
+ if (heightOriginal) {
+ if (!heightTruncated) {
+ return numberOfLines
+ } else {
+ if (allowExpand && !showAllText) {
+ return numberOfLines
+ } else {
+ return undefined
+ }
+ }
+ } else {
+ return undefined
+ }
+ }, [heightOriginal, heightTruncated, allowExpand, showAllText])
return (
- <>
+
numberOfLines ? shownLines : totalLines
- }
- style={{ lineHeight: StyleConstants.Font.LineHeight[size] }}
- onTextLayout={({ nativeEvent }) => {
- if (!textLoaded) {
- setTextLoaded(true)
- setTotalLines(nativeEvent.lines.length)
- setLineHeight(nativeEvent.lines[0].height)
+ style={{ lineHeight }}
+ children={children}
+ numberOfLines={calNumberOfLines}
+ onLayout={({ nativeEvent }) => {
+ if (!heightOriginal) {
+ setHeightOriginal(nativeEvent.layout.height)
+ } else {
+ if (!heightTruncated) {
+ setHeightTruncated(nativeEvent.layout.height)
+ } else {
+ if (heightOriginal > heightTruncated) {
+ setAllowExpand(true)
+ }
+ }
}
}}
- >
- {children}
-
- {totalLines && lineHeight && totalLines > shownLines && (
+ />
+ {allowExpand && (
{
- setShownLines(totalLines)
- }}
- style={{
- marginTop: -lineHeight
- }}
+ onPress={() => setShowAllText(!showAllText)}
+ style={{ marginTop: showAllText ? 0 : -lineHeight * 1.25 }}
>
= ({
color: theme.primary
}}
>
- 展开全文
+ {`${showAllText ? '折叠' : '展开'}${expandHint}`}
)}
- >
+
)
}, [])
diff --git a/src/components/Timelines/Timeline.tsx b/src/components/Timelines/Timeline.tsx
index 184cb05c..8440b6d1 100644
--- a/src/components/Timelines/Timeline.tsx
+++ b/src/components/Timelines/Timeline.tsx
@@ -55,7 +55,8 @@ const Timeline: React.FC = ({
fetchPreviousPage,
isFetchingPreviousPage,
hasNextPage,
- fetchNextPage
+ fetchNextPage,
+ isFetchingNextPage
} = useInfiniteQuery(queryKey, timelineFetch, {
getPreviousPageParam: firstPage => {
return firstPage.toots.length
@@ -133,7 +134,10 @@ const Timeline: React.FC = ({
() => ,
[status]
)
- const onEndReached = useCallback(() => !disableRefresh && fetchNextPage(), [])
+ const onEndReached = useCallback(
+ () => !disableRefresh && !isFetchingNextPage && fetchNextPage(),
+ [isFetchingNextPage]
+ )
const ListFooterComponent = useCallback(
() => ,
[hasNextPage]
diff --git a/src/components/Timelines/Timeline/Shared/Content.tsx b/src/components/Timelines/Timeline/Shared/Content.tsx
index 9fb27973..91088363 100644
--- a/src/components/Timelines/Timeline/Shared/Content.tsx
+++ b/src/components/Timelines/Timeline/Shared/Content.tsx
@@ -1,10 +1,7 @@
-import React, { useState } from 'react'
-import { LayoutAnimation, Pressable, Text, View } from 'react-native'
+import React from 'react'
+import { View } from 'react-native'
import ParseContent from '@components/ParseContent'
-import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
-import { LinearGradient } from 'expo-linear-gradient'
-import layoutAnimation from '@root/utils/styles/layoutAnimation'
export interface Props {
status: Mastodon.Status
@@ -17,11 +14,6 @@ const TimelineContent: React.FC = ({
numberOfLines,
highlighted = false
}) => {
- layoutAnimation()
- const { theme } = useTheme()
- const [spoilerCollapsed, setSpoilerCollapsed] = useState(false)
- const lineHeight = 28
-
return (
<>
{status.spoiler_text ? (
@@ -32,58 +24,16 @@ const TimelineContent: React.FC = ({
emojis={status.emojis}
numberOfLines={999}
/>
-
+
- setSpoilerCollapsed(!spoilerCollapsed)}
- style={{
- marginTop: spoilerCollapsed ? -lineHeight : 0
- }}
- >
-
-
- {spoilerCollapsed ? '展开' : '收起'}隐藏内容
-
-
-
>
) : (
= ({
size={highlighted ? 'L' : 'M'}
emojis={status.emojis}
mentions={status.mentions}
- {...(numberOfLines && { numberOfLines: numberOfLines })}
+ numberOfLines={numberOfLines}
/>
)}
>
diff --git a/yarn.lock b/yarn.lock
index cba12e31..22191206 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3400,25 +3400,25 @@ gl-react-blurhash@^1.0.0:
blurhash "^1.1.3"
gl-react-expo@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/gl-react-expo/-/gl-react-expo-4.0.1.tgz#7512b65fd7e27d84f3405e737f8b334aed6b69fc"
- integrity sha512-L4bwpqEolXmdc1YH8okN4qkfOW13/iLvevhJYgf2mHaLCRwhW1WDUJ18EEip8lUxaUmH9NmT9SC5DwMRiP0YSg==
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/gl-react-expo/-/gl-react-expo-4.1.0.tgz#0f3b13fae7fe490bc72fcf59c894605293da642d"
+ integrity sha512-3Q4LOBGYsNNqpLkwUsUlRrFCNLUqjVsVPKE3c6pLABfkNxyBacbDK3mg3T8XOD7jp+Vsp/Ic9McjICMsYHANJw==
dependencies:
invariant "^2.2.4"
webgltexture-loader-expo "1.0.0"
gl-react@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/gl-react/-/gl-react-4.0.1.tgz#6b747084237dc2209eb3ed05162bb5941c5a6e94"
- integrity sha512-/+wbFHVeh21wOS6g3v7r/zAdXoYMqn7xCB0CwLwMxBUwUsnV0jcvGS+8HDoup9Yd20xGt77p2c3gmrt2XtEEgg==
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/gl-react/-/gl-react-4.1.0.tgz#b7623555a4c3ba92a1ccbbb122c28c46231cd863"
+ integrity sha512-hTvxQHN2wxLfbA4c6mRcMdXWjA0/8UY2Sxn5eNre0DOrcauBj/+vMeAMbL2+zwE1BfVYnraE4cvKJTIzFIeBLw==
dependencies:
gl-shader "^4.2.1"
invariant "^2.2.4"
- ndarray "^1.0.18"
+ ndarray "^1.0.19"
prop-types "^15.7.2"
- typedarray-pool "^1.1.0"
+ typedarray-pool "^1.2.0"
webgltexture-loader "1.0.0"
- webgltexture-loader-ndarray "1.0.0"
+ webgltexture-loader-ndarray "1.1.0"
gl-shader@^4.2.1:
version "4.2.1"
@@ -4811,7 +4811,7 @@ ndarray-ops@^1.2.2:
dependencies:
cwise-compiler "^1.0.0"
-ndarray@^1.0.18:
+ndarray@^1.0.19:
version "1.0.19"
resolved "https://registry.yarnpkg.com/ndarray/-/ndarray-1.0.19.tgz#6785b5f5dfa58b83e31ae5b2a058cfd1ab3f694e"
integrity sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==
@@ -6365,7 +6365,7 @@ type-fest@^0.7.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48"
integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
-typedarray-pool@^1.1.0:
+typedarray-pool@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/typedarray-pool/-/typedarray-pool-1.2.0.tgz#e7e90720144ba02b9ed660438af6f3aacfe33ac3"
integrity sha512-YTSQbzX43yvtpfRtIDAYygoYtgT+Rpjuxy9iOpczrjpXLgGoyG7aS5USJXV2d3nn8uHTeb9rXDvzS27zUg5KYQ==
@@ -6613,14 +6613,14 @@ webgltexture-loader-expo@1.0.0:
dependencies:
webgltexture-loader "^1.0.0"
-webgltexture-loader-ndarray@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/webgltexture-loader-ndarray/-/webgltexture-loader-ndarray-1.0.0.tgz#844181c4cbe0cbc066750d66412c11d9205ad79a"
- integrity sha512-ocEStCCkihBu+PyMr14ke2vv08c5wVObP5mH9AuPICcBvaS8zfxvMpoGc9dIxOxBC1reI/lzmpYxpYdoY/Ke8g==
+webgltexture-loader-ndarray@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/webgltexture-loader-ndarray/-/webgltexture-loader-ndarray-1.1.0.tgz#20869150e79dfb6190cbd6bedafacda262e29a5e"
+ integrity sha512-t9Q4x5do5feHjMOJLCg8UdQVx1eInnWXvgAqaL9NJJSL5pzI59Ynx3ZZSw3QqGxj15iRbYij7vK8BCIDyp5EZA==
dependencies:
- ndarray "^1.0.18"
+ ndarray "^1.0.19"
ndarray-ops "^1.2.2"
- typedarray-pool "^1.1.0"
+ typedarray-pool "^1.2.0"
webgltexture-loader "^1.0.0"
webgltexture-loader@1.0.0, webgltexture-loader@^1.0.0: