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

Sharing works in simulator

This commit is contained in:
Zhiyuan Zheng
2022-05-02 22:31:22 +02:00
parent 829a25b76b
commit 43c2297387
22 changed files with 1301 additions and 114 deletions

View File

@ -1,3 +1,4 @@
import apiInstance from '@api/instance'
import analytics from '@components/analytics'
import { HeaderLeft, HeaderRight } from '@components/Header'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
@ -41,6 +42,7 @@ import { useSelector } from 'react-redux'
import * as Sentry from 'sentry-expo'
import ComposeDraftsList from './Compose/DraftsList'
import ComposeEditAttachment from './Compose/EditAttachment'
import { uploadAttachment } from './Compose/Root/Footer/addAttachment'
import ComposeContext from './Compose/utils/createContext'
import composeInitialState from './Compose/utils/initialState'
import composeParseState from './Compose/utils/parseState'
@ -135,7 +137,36 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
])
useEffect(() => {
const uploadImage = async ({
type,
uri
}: {
type: 'image' | 'video'
uri: string
}) => {
await uploadAttachment({
composeDispatch,
imageInfo: { type, uri, width: 100, height: 100 }
})
}
switch (params?.type) {
case 'share':
if (params.text) {
formatText({
textInput: 'text',
composeDispatch,
content: params.text,
disableDebounce: true
})
}
if (params.images?.length) {
params.images.forEach(image => {
uploadImage({ type: 'image', uri: image.uri })
})
} else if (params.video) {
uploadImage({ type: 'video', uri: params.video.uri })
}
break
case 'edit':
case 'deleteEdit':
if (params.incomingStatus.spoiler_text) {

View File

@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'
import { Pressable, StyleSheet, View } from 'react-native'
import { useSelector } from 'react-redux'
import ComposeContext from '../utils/createContext'
import addAttachment from './Footer/addAttachment'
import chooseAndUploadAttachment from './Footer/addAttachment'
const ComposeActions: React.FC = () => {
const { showActionSheetWithOptions } = useActionSheet()
@ -41,7 +41,7 @@ const ComposeActions: React.FC = () => {
analytics('compose_actions_attachment_press', {
count: composeState.attachments.uploads.length
})
return await addAttachment({
return await chooseAndUploadAttachment({
composeDispatch,
showActionSheetWithOptions
})

View File

@ -27,7 +27,7 @@ import {
import { Circle } from 'react-native-animated-spinkit'
import ComposeContext from '../../utils/createContext'
import { ExtendedAttachment } from '../../utils/types'
import addAttachment from './addAttachment'
import chooseAndUploadAttachment from './addAttachment'
export interface Props {
accessibleRefAttachments: RefObject<View>
@ -218,7 +218,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
]}
onPress={async () => {
analytics('compose_attachment_add_container_press')
await addAttachment({ composeDispatch, showActionSheetWithOptions })
await chooseAndUploadAttachment({ composeDispatch, showActionSheetWithOptions })
}}
>
<Button
@ -229,7 +229,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
overlay
onPress={async () => {
analytics('compose_attachment_add_button_press')
await addAttachment({ composeDispatch, showActionSheetWithOptions })
await chooseAndUploadAttachment({ composeDispatch, showActionSheetWithOptions })
}}
style={{
position: 'absolute',

View File

@ -17,114 +17,127 @@ export interface Props {
) => void
}
const addAttachment = async ({
export const uploadAttachment = async ({
composeDispatch,
imageInfo
}: {
composeDispatch: Dispatch<ComposeAction>
imageInfo: Pick<ImageInfo, 'type' | 'uri' | 'width' | 'height'>
}) => {
const hash = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
imageInfo.uri + Math.random()
)
let attachmentType: string
switch (imageInfo.type) {
case 'image':
console.log('uri', imageInfo.uri)
attachmentType = `image/${imageInfo.uri.split('.')[1]}`
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, local_thumbnail: imageInfo.uri, hash },
uploading: true
}
})
break
case 'video':
attachmentType = `video/${imageInfo.uri.split('.')[1]}`
VideoThumbnails.getThumbnailAsync(imageInfo.uri)
.then(({ uri, width, height }) =>
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: {
...imageInfo,
local_thumbnail: uri,
hash,
width,
height
},
uploading: true
}
})
)
.catch(() =>
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, hash },
uploading: true
}
})
)
break
default:
attachmentType = 'unknown'
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, hash },
uploading: true
}
})
break
}
const uploadFailed = () => {
composeDispatch({
type: 'attachment/upload/fail',
payload: hash
})
Alert.alert(
i18next.t(
'screenCompose:content.root.actions.attachment.failed.alert.title'
),
undefined,
[
{
text: i18next.t(
'screenCompose:content.root.actions.attachment.failed.alert.button'
),
onPress: () => {}
}
]
)
}
const formData = new FormData()
formData.append('file', {
// @ts-ignore
uri: imageInfo.uri,
name: attachmentType,
type: attachmentType
})
return apiInstance<Mastodon.Attachment>({
method: 'post',
url: 'media',
body: formData
})
.then(res => {
if (res.body.id) {
composeDispatch({
type: 'attachment/upload/end',
payload: { remote: res.body, local: imageInfo }
})
} else {
uploadFailed()
}
})
.catch(() => {
uploadFailed()
})
}
const chooseAndUploadAttachment = async ({
composeDispatch,
showActionSheetWithOptions
}: Props): Promise<any> => {
const uploader = async (imageInfo: ImageInfo) => {
const hash = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
imageInfo.uri + Math.random()
)
let attachmentType: string
switch (imageInfo.type) {
case 'image':
attachmentType = `image/${imageInfo.uri.split('.')[1]}`
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, local_thumbnail: imageInfo.uri, hash },
uploading: true
}
})
break
case 'video':
attachmentType = `video/${imageInfo.uri.split('.')[1]}`
VideoThumbnails.getThumbnailAsync(imageInfo.uri)
.then(({ uri }) =>
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, local_thumbnail: uri, hash },
uploading: true
}
})
)
.catch(() =>
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, hash },
uploading: true
}
})
)
break
default:
attachmentType = 'unknown'
composeDispatch({
type: 'attachment/upload/start',
payload: {
local: { ...imageInfo, hash },
uploading: true
}
})
break
}
const uploadFailed = () => {
composeDispatch({
type: 'attachment/upload/fail',
payload: hash
})
Alert.alert(
i18next.t(
'screenCompose:content.root.actions.attachment.failed.alert.title'
),
undefined,
[
{
text: i18next.t(
'screenCompose:content.root.actions.attachment.failed.alert.button'
),
onPress: () => {}
}
]
)
}
const formData = new FormData()
formData.append('file', {
// @ts-ignore
uri: imageInfo.uri,
name: attachmentType,
type: attachmentType
})
return apiInstance<Mastodon.Attachment>({
method: 'post',
url: 'media',
body: formData
})
.then(res => {
if (res.body.id) {
composeDispatch({
type: 'attachment/upload/end',
payload: { remote: res.body, local: imageInfo }
})
} else {
uploadFailed()
}
})
.catch(() => {
uploadFailed()
})
}
const result = await mediaSelector({ showActionSheetWithOptions })
await uploader(result)
await uploadAttachment({ composeDispatch, imageInfo: result })
}
export default addAttachment
export default chooseAndUploadAttachment

View File

@ -38,6 +38,8 @@ const composeParseState = (
params: NonNullable<RootStackParamList['Screen-Compose']>
): ComposeState => {
switch (params.type) {
case 'share':
return { ...composeInitialState, dirty: true, timestamp: Date.now() }
case 'edit':
case 'deleteEdit':
return {