diff --git a/src/components/Toot/Actioned.jsx b/src/components/Toot/Actioned.jsx
index 4ead4c58..e0554702 100644
--- a/src/components/Toot/Actioned.jsx
+++ b/src/components/Toot/Actioned.jsx
@@ -75,7 +75,8 @@ const styles = StyleSheet.create({
})
Actioned.propTypes = {
- action: PropTypes.oneOf(['favourite', 'follow', 'poll', 'reblog']).isRequired,
+ action: PropTypes.oneOf(['favourite', 'follow', 'mention', 'poll', 'reblog'])
+ .isRequired,
name: PropTypes.string,
emojis: PropTypes.arrayOf(propTypesEmoji),
notification: PropTypes.bool
diff --git a/src/components/Toot/Attachment.jsx b/src/components/Toot/Attachment.jsx
new file mode 100644
index 00000000..ef44da58
--- /dev/null
+++ b/src/components/Toot/Attachment.jsx
@@ -0,0 +1,81 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import propTypesAttachment from 'src/prop-types/attachment'
+import { Text, View } from 'react-native'
+
+import AttachmentImage from './Attachment/AttachmentImage'
+import AttachmentVideo from './Attachment/AttachmentVideo'
+
+export default function Attachment ({ media_attachments, sensitive, width }) {
+ let attachment
+ let attachmentHeight
+ // if (width) {}
+ switch (media_attachments[0].type) {
+ case 'unknown':
+ attachment = 文件不支持
+ attachmentHeight = 25
+ break
+ case 'image':
+ attachment = (
+
+ )
+ attachmentHeight = width / 2
+ break
+ case 'gifv':
+ attachment = (
+
+ )
+ attachmentHeight =
+ (width / media_attachments[0].meta.original.width) *
+ media_attachments[0].meta.original.height
+ break
+ case 'video':
+ attachment = (
+
+ )
+ attachmentHeight =
+ (width / media_attachments[0].meta.original.width) *
+ media_attachments[0].meta.original.height
+ break
+ // case 'audio':
+ // attachment = (
+ //
+ // )
+ // break
+ }
+
+ return (
+
+ {attachment}
+
+ )
+}
+
+Attachment.propTypes = {
+ media_attachments: PropTypes.arrayOf(propTypesAttachment),
+ sensitive: PropTypes.bool.isRequired,
+ width: PropTypes.number.isRequired
+}
diff --git a/src/components/Toot/Attachment/AttachmentImage.jsx b/src/components/Toot/Attachment/AttachmentImage.jsx
new file mode 100644
index 00000000..1c2eda89
--- /dev/null
+++ b/src/components/Toot/Attachment/AttachmentImage.jsx
@@ -0,0 +1,102 @@
+import React, { useEffect, useState } from 'react'
+import PropTypes from 'prop-types'
+import propTypesAttachment from 'src/prop-types/attachment'
+import { Button, Image, Modal, StyleSheet, Pressable, View } from 'react-native'
+import ImageViewer from 'react-native-image-zoom-viewer'
+
+export default function AttachmentImage ({ media_attachments, sensitive, width }) {
+ const [mediaSensitive, setMediaSensitive] = useState(sensitive)
+ const [imageModalVisible, setImageModalVisible] = useState(false)
+ const [imageModalIndex, setImageModalIndex] = useState(0)
+ useEffect(() => {
+ if (sensitive && mediaSensitive === false) {
+ setTimeout(() => {
+ setMediaSensitive(true)
+ }, 10000)
+ }
+ }, [mediaSensitive])
+
+ let images = []
+ media_attachments = media_attachments.map((m, i) => {
+ images.push({
+ url: m.url,
+ width: m.meta.original.width,
+ height: m.meta.original.height
+ })
+ return (
+ {
+ setImageModalIndex(i)
+ setImageModalVisible(true)
+ }}
+ >
+
+
+ )
+ })
+
+ return (
+ <>
+
+ {media_attachments}
+ {mediaSensitive && (
+
+
+ )}
+
+
+ setImageModalVisible(false)}
+ enableSwipeDown={true}
+ swipeDownThreshold={100}
+ useNativeDriver={true}
+ />
+
+ >
+ )
+}
+
+const styles = StyleSheet.create({
+ media: {
+ flex: 1,
+ flexDirection: 'column',
+ flexWrap: 'wrap',
+ justifyContent: 'space-between',
+ alignItems: 'stretch',
+ alignContent: 'stretch'
+ },
+ image: {
+ width: '100%',
+ height: '100%'
+ }
+})
+
+AttachmentImage.propTypes = {
+ media_attachments: PropTypes.arrayOf(propTypesAttachment),
+ sensitive: PropTypes.bool.isRequired,
+ width: PropTypes.number.isRequired
+}
diff --git a/src/components/Toot/Attachment/AttachmentVideo.jsx b/src/components/Toot/Attachment/AttachmentVideo.jsx
new file mode 100644
index 00000000..b789b23a
--- /dev/null
+++ b/src/components/Toot/Attachment/AttachmentVideo.jsx
@@ -0,0 +1,72 @@
+import React, { useRef, useState } from 'react'
+import PropTypes from 'prop-types'
+import propTypesAttachment from 'src/prop-types/attachment'
+import { Pressable, View } from 'react-native'
+import { Video } from 'expo-av'
+import { Feather } from '@expo/vector-icons'
+
+export default function AttachmentVideo ({
+ media_attachments,
+ sensitive,
+ width
+}) {
+ const videoPlayer = useRef()
+ const [mediaSensitive, setMediaSensitive] = useState(sensitive)
+ const [videoPlay, setVideoPlay] = useState(false)
+
+ const video = media_attachments[0]
+ const videoWidth = width
+ const videoHeight =
+ (width / video.meta.original.width) * video.meta.original.height
+
+ return (
+
+
+ {!videoPlay && (
+ {
+ setMediaSensitive(false)
+ videoPlayer.current.presentFullscreenPlayer()
+ setVideoPlay(true)
+ }}
+ style={{
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: '100%',
+ height: '100%',
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: 'rgba(0, 0, 0, 0.25)'
+ }}
+ >
+
+
+ )}
+
+ )
+}
+
+AttachmentVideo.propTypes = {
+ media_attachments: PropTypes.arrayOf(propTypesAttachment),
+ sensitive: PropTypes.bool.isRequired,
+ width: PropTypes.number.isRequired
+}
diff --git a/src/components/Toot/Media.jsx b/src/components/Toot/Media.jsx
deleted file mode 100644
index 555d0756..00000000
--- a/src/components/Toot/Media.jsx
+++ /dev/null
@@ -1,138 +0,0 @@
-import React, { useEffect, useState } from 'react'
-import PropTypes from 'prop-types'
-import propTypesAttachment from 'src/prop-types/attachment'
-import {
- Button,
- Image,
- Modal,
- StyleSheet,
- Text,
- Pressable,
- View
-} from 'react-native'
-import ImageViewer from 'react-native-image-zoom-viewer'
-
-export default function Media ({ media_attachments, sensitive, width }) {
- const [mediaSensitive, setMediaSensitive] = useState(sensitive)
- const [imageModalVisible, setImageModalVisible] = useState(false)
- const [imageModalIndex, setImageModalIndex] = useState(0)
- useEffect(() => {
- if (sensitive && mediaSensitive === false) {
- setTimeout(() => {
- setMediaSensitive(true)
- }, 10000)
- }
- }, [mediaSensitive])
-
- let media
- let images = []
- if (width) {
- media_attachments = media_attachments.map((m, i) => {
- switch (m.type) {
- case 'unknown':
- return 文件不支持
- case 'image':
- images.push({
- url: m.url,
- width: m.meta.original.width,
- height: m.meta.original.height
- })
- return (
- {
- setImageModalIndex(i)
- setImageModalVisible(true)
- }}
- >
-
-
- )
- }
- })
- if (images) {
- media = (
- <>
-
- {media_attachments}
- {mediaSensitive && (
-
-
- )}
-
-
- setImageModalVisible(false)}
- enableSwipeDown={true}
- swipeDownThreshold={100}
- useNativeDriver={true}
- />
-
- >
- )
- } else {
- media = {media_attachments}
- }
- } else {
- media = <>>
- }
-
- return (
- media_attachments.length > 0 && (
-
- {media}
-
- )
- )
-}
-
-const styles = StyleSheet.create({
- media: {
- flex: 1,
- flexDirection: 'column',
- flexWrap: 'wrap',
- justifyContent: 'space-between',
- alignItems: 'stretch',
- alignContent: 'stretch'
- },
- image: {
- width: '100%',
- height: '100%'
- }
-})
-
-Media.propTypes = {
- media_attachments: PropTypes.arrayOf(propTypesAttachment),
- sensitive: PropTypes.bool.isRequired,
- width: PropTypes.number.isRequired
-}
diff --git a/src/components/TootNotification.jsx b/src/components/TootNotification.jsx
index 77bbdfa8..93771b3c 100644
--- a/src/components/TootNotification.jsx
+++ b/src/components/TootNotification.jsx
@@ -8,7 +8,7 @@ import Avatar from './Toot/Avatar'
import Header from './Toot/Header'
import Content from './Toot/Content'
import Poll from './Toot/Poll'
-import Media from './Toot/Media'
+import Attachment from './Toot/Attachment'
import Card from './Toot/Card'
import Actions from './Toot/Actions'
@@ -53,7 +53,7 @@ export default function TootNotification ({ toot }) {
)}
{toot.status.poll && }
{toot.status.media_attachments && (
-
{/* Can pass toot info to next page to speed up performance */}
- navigation.navigate('Toot', { toot: actualContent.id })
- }
+ // onPress={() =>
+ // navigation.navigate('Toot', { toot: actualContent.id })
+ // }
>
{actualContent.content ? (
>
)}
{actualContent.poll && }
- {actualContent.media_attachments && (
- 0 && (
+
{() => }
+
+ {sharedScreens(Stack)}
)
}
diff --git a/src/stacks/Shared/sharedScreens.jsx b/src/stacks/Shared/sharedScreens.jsx
new file mode 100644
index 00000000..f5a28656
--- /dev/null
+++ b/src/stacks/Shared/sharedScreens.jsx
@@ -0,0 +1,45 @@
+import React from 'react'
+
+import Account from 'src/stacks/Shared/Account'
+import Hashtag from 'src/stacks/Shared/Hashtag'
+import Toot from 'src/stacks/Shared/Toot'
+import Webview from 'src/stacks/Shared/Webview'
+
+export default function sharedScreens (Stack) {
+ return [
+ {}
+ }}
+ />,
+ ({
+ title: `#${decodeURIComponent(route.params.hashtag)}`
+ })}
+ />,
+ ({
+ title: '对话'
+ })}
+ />,
+ ({
+ // title: `${route.params.domain}`
+ // })}
+ />
+ ]
+}
diff --git a/src/stacks/common/Timeline.jsx b/src/stacks/common/Timeline.jsx
index 8916c8dc..b63216f5 100644
--- a/src/stacks/common/Timeline.jsx
+++ b/src/stacks/common/Timeline.jsx
@@ -22,10 +22,12 @@ export default function Timeline ({
const [timelineReady, setTimelineReady] = useState(false)
useEffect(() => {
- if (state.status === 'idle') {
+ let mounted = true
+ if (state.status === 'idle' && mounted) {
dispatch(fetch({ page, hashtag, list, toot, account }))
setTimelineReady(true)
}
+ return () => (mounted = false)
}, [state, dispatch])
let content
diff --git a/src/stacks/common/TimelinesCombined.jsx b/src/stacks/common/TimelinesCombined.jsx
index 8eedae0a..2cd0e2d1 100644
--- a/src/stacks/common/TimelinesCombined.jsx
+++ b/src/stacks/common/TimelinesCombined.jsx
@@ -6,10 +6,7 @@ import SegmentedControl from '@react-native-community/segmented-control'
import { Feather } from '@expo/vector-icons'
import Timeline from './Timeline'
-import Account from 'src/stacks/Shared/Account'
-import Hashtag from 'src/stacks/Shared/Hashtag'
-import Toot from 'src/stacks/Shared/Toot'
-import Webview from 'src/stacks/Shared/Webview'
+import sharedScreens from 'src/stacks/Shared/sharedScreens'
const Stack = createNativeStackNavigator()
@@ -93,36 +90,8 @@ export default function TimelinesCombined ({ name, content }) {
/>
)}
- {}
- }}
- />
- ({
- title: `#${decodeURIComponent(route.params.hashtag)}`
- })}
- />
- ({
- title: '对话'
- })}
- />
- ({
- // title: `${route.params.domain}`
- // })}
- />
+
+ {sharedScreens(Stack)}
)
}