1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Basic toot in timeline working

This commit is contained in:
Zhiyuan Zheng
2020-10-26 00:27:53 +01:00
parent 996cf0c1e7
commit eefa7e01bd
21 changed files with 483 additions and 284 deletions

View File

@ -8,7 +8,36 @@ import Header from './TootTimeline/Header'
import Content from './TootTimeline/Content'
import Actions from './TootTimeline/Actions'
// Maybe break away notification types? https://docs.joinmastodon.org/entities/notification/
export default function TootTimeline ({ item, notification }) {
let contentAggregated = {}
if (notification && item.status) {
contentAggregated = {
content: item.status.content,
emojis: item.status.emojis,
media_attachments: item.status.media_attachments,
mentions: item.status.mentions,
tags: item.status.tags
}
} else if (item.reblog) {
contentAggregated = {
content: item.reblog.content,
emojis: item.reblog.emojis,
media_attachments: item.reblog.media_attachments,
mentions: item.reblog.mentions,
tags: item.reblog.tags
}
} else {
contentAggregated = {
content: item.content,
emojis: item.emojis,
media_attachments: item.media_attachments,
mentions: item.mentions,
tags: item.tags
}
}
return (
<View style={styles.tootTimeline}>
{item.reblog && (
@ -19,7 +48,7 @@ export default function TootTimeline ({ item, notification }) {
)}
<View style={styles.toot}>
<Avatar uri={item.reblog?.account.avatar || item.account.avatar} />
<View style={{flexGrow: 1}}>
<View style={styles.details}>
<Header
name={
(item.reblog?.account.display_name
@ -34,9 +63,7 @@ export default function TootTimeline ({ item, notification }) {
created_at={item.created_at}
application={item.application || null}
/>
<Content
content={notification ? item.status.content : item.content}
/>
<Content {...contentAggregated} />
</View>
</View>
<Actions />
@ -51,7 +78,11 @@ const styles = StyleSheet.create({
padding: 12
},
toot: {
flex: 1,
flexDirection: 'row'
},
details: {
flex: 1
}
})

View File

@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Image, StyleSheet } from 'react-native'
import { Image, StyleSheet, View } from 'react-native'
export default function Avatar ({ uri }) {
return <Image source={{ uri: uri }} style={styles.avatar} />

View File

@ -1,29 +1,100 @@
import React, { useState } from 'react'
import React from 'react'
import PropTypes from 'prop-types'
import { Dimensions, StyleSheet, View } from 'react-native'
import HTML from 'react-native-render-html'
import { StyleSheet, Text } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import HTMLView from 'react-native-htmlview'
// !! Need to solve dimension issue
import Emojis from './Emojis'
export default function Content ({ content }) {
const [viewWidth, setViewWidth] = useState()
return (
content && (
<View
style={{ width: '100%' }}
onLayout={e => setViewWidth(e.nativeEvent.layout.width)}
>
{viewWidth && (
<HTML html={content} containerStyle={{ width: viewWidth }} />
)}
</View>
)
function renderNode (navigation, node, index, mentions) {
if (node.name == 'a') {
const classes = node.attribs.class
const href = node.attribs.href
if (classes) {
if (classes.includes('hashtag')) {
return (
<Text
key={index}
style={styles.a}
onPress={() => {
const tag = href.split(new RegExp(/\/tag\/(.*)|\/tags\/(.*)/))
navigation.navigate('Hashtag', {
hashtag: tag[1] || tag[2]
})
}}
>
{node.children[0].data}
{node.children[1]?.children[0].data}
</Text>
)
} else if (classes.includes('mention')) {
return (
<Text
key={index}
style={styles.a}
onPress={() => {
const username = href.split(new RegExp(/@(.*)/))
const usernameIndex = mentions.findIndex(
m => m.username === username[1]
)
navigation.navigate('Account', {
id: mentions[usernameIndex].id
})
}}
>
{node.children[0].data}
{node.children[1]?.children[0].data}
</Text>
)
}
} else {
const domain = href.split(new RegExp(/:\/\/(.*?)\//))
return (
<Text
key={index}
style={styles.a}
onPress={() => {
navigation.navigate('Webview', {
uri: href,
domain: domain[1]
})
}}
>
{domain[1]}
</Text>
)
}
}
}
export default function Content ({
content,
emojis,
media_attachments,
mentions,
tags
}) {
const navigation = useNavigation()
return content ? (
<HTMLView
value={content}
renderNode={(node, index) =>
renderNode(navigation, node, index, mentions)
}
TextComponent={({ children }) => (
<Emojis content={children} emojis={emojis} dimension={14} />
)}
/>
) : (
<></>
)
}
const styles = StyleSheet.create({
width: 50,
height: 50
a: {
color: 'blue'
}
})
Content.propTypes = {

View File

@ -15,7 +15,7 @@ export default function Header ({
const [since, setSince] = useState(relativeTime(created_at))
useEffect(() => {
const timer = setTimeout(() => {
setTimeout(() => {
setSince(relativeTime(created_at))
}, 1000)
})
@ -49,8 +49,7 @@ export default function Header ({
const styles = StyleSheet.create({
names: {
flexDirection: 'row',
marginBottom: 8
flexDirection: 'row'
},
name: {
flexDirection: 'row',
@ -66,6 +65,8 @@ const styles = StyleSheet.create({
created_at: {
fontSize: 12,
lineHeight: 12,
marginTop: 8,
marginBottom: 8,
marginRight: 8
},
application: {