Expandable content done

This commit is contained in:
Zhiyuan Zheng 2020-12-02 00:16:27 +01:00
parent 9bfee02484
commit 8986680c6d
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
8 changed files with 95 additions and 24 deletions

View File

@ -33,7 +33,6 @@ const App: React.FC = () => {
<PersistGate persistor={persistor}>
{bootstrapped => {
if (bootstrapped) {
console.log('Bootstrapped!')
require('src/i18n/i18n')
return (
<ThemeManager>

View File

@ -18,6 +18,7 @@
"expo-auth-session": "~2.0.0",
"expo-av": "~8.6.0",
"expo-image-picker": "~9.1.1",
"expo-linear-gradient": "~8.3.0",
"expo-localization": "^9.0.0",
"expo-secure-store": "~9.2.0",
"expo-splash-screen": "~0.6.1",

View File

@ -1 +1,2 @@
declare module 'react-native-toast-message'
declare module 'react-native-htmlview'

View File

@ -31,7 +31,7 @@ const MenuContainer: React.FC<Props> = ({ ...props }) => {
const styles = StyleSheet.create({
base: {
borderTopWidth: 1,
marginBottom: StyleConstants.Spacing.Global.PagePadding
marginBottom: StyleConstants.Spacing.L
}
})

View File

@ -1,5 +1,5 @@
import React, { useCallback } from 'react'
import { StyleSheet, Text, View } from 'react-native'
import React, { useCallback, useState } from 'react'
import { Pressable, StyleSheet, Text } from 'react-native'
import HTMLView from 'react-native-htmlview'
import { useNavigation } from '@react-navigation/native'
@ -7,12 +7,14 @@ import Emojis from 'src/components/Timelines/Timeline/Shared/Emojis'
import { useTheme } from 'src/utils/styles/ThemeManager'
import { Feather } from '@expo/vector-icons'
import { StyleConstants } from 'src/utils/styles/constants'
import { LinearGradient } from 'expo-linear-gradient'
// Prevent going to the same hashtag multiple times
const renderNode = ({
theme,
node,
index,
size,
navigation,
mentions,
showFullLink
@ -20,6 +22,7 @@ const renderNode = ({
theme: any
node: any
index: number
size: number
navigation: any
mentions?: Mastodon.Mention[]
showFullLink: boolean
@ -32,7 +35,7 @@ const renderNode = ({
return (
<Text
key={index}
style={{ color: theme.link }}
style={{ color: theme.link, fontSize: size }}
onPress={() => {
const tag = href.split(new RegExp(/\/tag\/(.*)|\/tags\/(.*)/))
navigation.push('Screen-Shared-Hashtag', {
@ -48,7 +51,7 @@ const renderNode = ({
return (
<Text
key={index}
style={{ color: theme.link }}
style={{ color: theme.link, fontSize: size }}
onPress={() => {
const username = href.split(new RegExp(/@(.*)/))
const usernameIndex = mentions.findIndex(
@ -69,7 +72,7 @@ const renderNode = ({
return (
<Text
key={index}
style={{ color: theme.link }}
style={{ color: theme.link, fontSize: size }}
onPress={() => {
navigation.navigate('Screen-Shared-Webview', {
uri: href,
@ -77,11 +80,7 @@ const renderNode = ({
})
}}
>
<Feather
name='external-link'
size={StyleConstants.Font.Size.M}
color={theme.link}
/>{' '}
<Feather name='external-link' size={size} color={theme.link} />{' '}
{showFullLink ? href : domain[1]}
</Text>
)
@ -111,7 +110,15 @@ const ParseContent: React.FC<Props> = ({
const renderNodeCallback = useCallback(
(node, index) =>
renderNode({ theme, node, index, navigation, mentions, showFullLink }),
renderNode({
theme,
node,
index,
size,
navigation,
mentions,
showFullLink
}),
[]
)
const textComponent = useCallback(
@ -124,10 +131,62 @@ const ParseContent: React.FC<Props> = ({
[]
)
const rootComponent = useCallback(({ children }) => {
const { theme } = useTheme()
const [textLoaded, setTextLoaded] = useState(false)
const [totalLines, setTotalLines] = useState<number | undefined>()
const [lineHeight, setLineHeight] = useState<number | undefined>()
const [shownLines, setShownLines] = useState(numberOfLines)
return (
<Text numberOfLines={numberOfLines} style={styles.root}>
{children}
</Text>
<>
<Text
numberOfLines={
totalLines && totalLines > numberOfLines ? shownLines : totalLines
}
style={styles.root}
onTextLayout={({ nativeEvent }) => {
if (!textLoaded) {
setTextLoaded(true)
setTotalLines(nativeEvent.lines.length)
setLineHeight(nativeEvent.lines[0].height)
}
}}
>
{children}
</Text>
{totalLines && lineHeight && totalLines > shownLines && (
<Pressable
onPress={() => {
setShownLines(totalLines)
}}
style={{
marginTop: -lineHeight
}}
>
<LinearGradient
colors={[
theme.backgroundGradientStart,
theme.backgroundGradientEnd
]}
locations={[0, lineHeight / (StyleConstants.Font.Size.S * 5)]}
style={{
paddingTop: StyleConstants.Font.Size.S * 2,
paddingBottom: StyleConstants.Font.Size.S
}}
>
<Text
style={{
textAlign: 'center',
fontSize: StyleConstants.Font.Size.S,
color: theme.primary
}}
>
</Text>
</LinearGradient>
</Pressable>
)}
</>
)
}, [])

View File

@ -12,13 +12,15 @@ export interface Props {
emojis: Mastodon.Emoji[]
mentions: Mastodon.Mention[]
spoiler_text?: string
numberOfLines?: number
}
const Content: React.FC<Props> = ({
content,
emojis,
mentions,
spoiler_text
spoiler_text,
numberOfLines
}) => {
const { theme } = useTheme()
const [spoilerCollapsed, setSpoilerCollapsed] = useState(true)
@ -28,11 +30,13 @@ const Content: React.FC<Props> = ({
{content &&
(spoiler_text ? (
<>
<Text>
<Text style={{ fontSize: StyleConstants.Font.Size.M }}>
{spoiler_text}{' '}
<Text
onPress={() => setSpoilerCollapsed(!spoilerCollapsed)}
style={{ color: theme.link }}
style={{
color: theme.link
}}
>
{spoilerCollapsed ? '点击展开' : '点击收起'}
</Text>
@ -43,6 +47,7 @@ const Content: React.FC<Props> = ({
size={StyleConstants.Font.Size.M}
emojis={emojis}
mentions={mentions}
{...(numberOfLines && { numberOfLines: numberOfLines })}
/>
</Collapsible>
</>
@ -52,6 +57,7 @@ const Content: React.FC<Props> = ({
size={StyleConstants.Font.Size.M}
emojis={emojis}
mentions={mentions}
{...(numberOfLines && { numberOfLines: numberOfLines })}
/>
))}
</>

View File

@ -5,6 +5,8 @@ export type ColorDefinitions =
| 'secondary'
| 'disabled'
| 'background'
| 'backgroundGradientStart'
| 'backgroundGradientEnd'
| 'link'
| 'border'
| 'separator'
@ -34,6 +36,14 @@ const themeColors: {
light: 'rgb(255, 255, 255)',
dark: 'rgb(0, 0, 0)'
},
backgroundGradientStart: {
light: 'rgba(255, 255, 255, 0.5)',
dark: 'rgba(0, 0, 0, 0.5)'
},
backgroundGradientEnd: {
light: 'rgba(255, 255, 255, 1)',
dark: 'rgba(0, 0, 0, 1)'
},
link: {
light: 'rgb(0, 122, 255)',
dark: 'rgb(10, 132, 255)'

View File

@ -1481,11 +1481,6 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
"@types/webpack-env@^1.16.0":
version "1.16.0"
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.0.tgz#8c0a9435dfa7b3b1be76562f3070efb3f92637b4"
integrity sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw==
"@types/yargs-parser@*":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"