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:
@ -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) {
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user