tooot/src/screens/Compose/Root/Footer/addAttachment.ts

246 lines
7.1 KiB
TypeScript
Raw Normal View History

2020-12-30 00:56:25 +01:00
import client from '@api/client'
import * as ImagePicker from 'expo-image-picker'
2021-01-04 14:55:34 +01:00
import * as Crypto from 'expo-crypto'
2020-12-30 00:56:25 +01:00
import { ImageInfo } from 'expo-image-picker/build/ImagePicker.types'
import * as VideoThumbnails from 'expo-video-thumbnails'
import { Dispatch } from 'react'
2021-01-13 01:03:46 +01:00
import { Alert, Linking } from 'react-native'
2021-01-19 01:13:45 +01:00
import { ComposeAction } from '../../utils/types'
2021-01-13 01:03:46 +01:00
import { ActionSheetOptions } from '@expo/react-native-action-sheet'
2021-01-19 01:13:45 +01:00
import i18next from 'i18next'
2021-01-24 02:25:43 +01:00
import analytics from '@components/analytics'
2020-12-30 00:56:25 +01:00
export interface Props {
composeDispatch: Dispatch<ComposeAction>
2021-01-14 00:43:35 +01:00
showActionSheetWithOptions: (
options: ActionSheetOptions,
callback: (i: number) => void
) => void
2020-12-30 00:56:25 +01:00
}
2021-01-14 00:43:35 +01:00
const addAttachment = async ({
composeDispatch,
showActionSheetWithOptions
}: Props): Promise<any> => {
2021-01-04 14:55:34 +01:00
const uploadAttachment = async (result: ImageInfo) => {
const hash = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
result.uri + Math.random()
)
2021-01-14 00:43:35 +01:00
let attachmentType: string
// https://github.com/expo/expo/issues/11214
const attachmentUri = result.uri.replace('file:/data', 'file:///data')
2020-12-30 00:56:25 +01:00
switch (result.type) {
case 'image':
2021-01-14 00:43:35 +01:00
attachmentType = `image/${attachmentUri.split('.')[1]}`
2020-12-30 00:56:25 +01:00
composeDispatch({
type: 'attachment/upload/start',
payload: {
2021-01-14 00:43:35 +01:00
local: { ...result, local_thumbnail: attachmentUri, hash },
2020-12-30 00:56:25 +01:00
uploading: true
}
})
break
case 'video':
2021-01-14 00:43:35 +01:00
attachmentType = `video/${attachmentUri.split('.')[1]}`
VideoThumbnails.getThumbnailAsync(attachmentUri)
2020-12-30 00:56:25 +01:00
.then(({ uri }) =>
composeDispatch({
type: 'attachment/upload/start',
payload: {
2021-01-04 14:55:34 +01:00
local: { ...result, local_thumbnail: uri, hash },
2020-12-30 00:56:25 +01:00
uploading: true
}
})
)
.catch(() =>
composeDispatch({
type: 'attachment/upload/start',
payload: {
2021-01-04 14:55:34 +01:00
local: { ...result, hash },
2020-12-30 00:56:25 +01:00
uploading: true
}
})
)
break
default:
2021-01-14 00:43:35 +01:00
attachmentType = 'unknown'
2020-12-30 00:56:25 +01:00
composeDispatch({
type: 'attachment/upload/start',
payload: {
2021-01-04 14:55:34 +01:00
local: { ...result, hash },
2020-12-30 00:56:25 +01:00
uploading: true
}
})
break
}
2021-01-19 01:13:45 +01:00
const uploadFailed = () => {
composeDispatch({
type: 'attachment/upload/fail',
payload: hash
})
Alert.alert(
i18next.t(
'sharedCompose:content.root.actions.attachment.failed.alert.title'
),
undefined,
[
{
text: i18next.t(
'sharedCompose:content.root.actions.attachment.failed.alert.button'
),
onPress: () => {}
}
]
)
}
2020-12-30 00:56:25 +01:00
const formData = new FormData()
formData.append('file', {
// @ts-ignore
2021-01-14 00:43:35 +01:00
uri: attachmentUri,
name: attachmentType,
type: attachmentType
2020-12-30 00:56:25 +01:00
})
2021-01-07 19:13:09 +01:00
return client<Mastodon.Attachment>({
2020-12-30 00:56:25 +01:00
method: 'post',
instance: 'local',
url: 'media',
body: formData
})
2021-01-07 19:13:09 +01:00
.then(res => {
if (res.id) {
2020-12-30 00:56:25 +01:00
composeDispatch({
type: 'attachment/upload/end',
2021-01-07 19:13:09 +01:00
payload: { remote: res, local: result }
2020-12-30 00:56:25 +01:00
})
} else {
2021-01-19 01:13:45 +01:00
uploadFailed()
2020-12-30 00:56:25 +01:00
}
})
.catch(() => {
2021-01-19 01:13:45 +01:00
uploadFailed()
2020-12-30 00:56:25 +01:00
})
}
2021-01-13 01:03:46 +01:00
showActionSheetWithOptions(
2020-12-30 00:56:25 +01:00
{
2021-01-19 01:13:45 +01:00
options: [
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.options.library'
),
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.options.photo'
),
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.options.cancel'
)
],
2020-12-30 00:56:25 +01:00
cancelButtonIndex: 2
},
async buttonIndex => {
if (buttonIndex === 0) {
2020-12-30 01:33:58 +01:00
const {
status
} = await ImagePicker.requestMediaLibraryPermissionsAsync()
if (status !== 'granted') {
2021-01-19 01:13:45 +01:00
Alert.alert(
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.library.alert.title'
),
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.library.alert.message'
),
[
{
text: i18next.t(
'sharedCompose:content.root.actions.attachment.actions.library.alert.buttons.cancel'
),
style: 'cancel',
2021-01-24 02:25:43 +01:00
onPress: () => {
analytics('compose_addattachment_medialibrary_nopermission', {
action: 'cancel'
})
}
2021-01-19 01:13:45 +01:00
},
{
text: i18next.t(
'sharedCompose:content.root.actions.attachment.actions.library.alert.buttons.settings'
),
style: 'default',
2021-01-24 02:25:43 +01:00
onPress: () => {
analytics('compose_addattachment_medialibrary_nopermission', {
action: 'settings'
})
Linking.openURL('app-settings:')
}
2021-01-19 01:13:45 +01:00
}
]
)
2020-12-30 01:33:58 +01:00
} else {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
exif: false
})
2020-12-30 00:56:25 +01:00
2020-12-30 01:33:58 +01:00
if (!result.cancelled) {
uploadAttachment(result)
}
2020-12-30 00:56:25 +01:00
}
} else if (buttonIndex === 1) {
2020-12-30 01:33:58 +01:00
const { status } = await ImagePicker.requestCameraPermissionsAsync()
if (status !== 'granted') {
2021-01-19 01:13:45 +01:00
Alert.alert(
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.photo.alert.title'
),
i18next.t(
'sharedCompose:content.root.actions.attachment.actions.photo.alert.message'
),
[
{
text: i18next.t(
'sharedCompose:content.root.actions.attachment.actions.photo.alert.buttons.cancel'
),
style: 'cancel',
2021-01-24 02:25:43 +01:00
onPress: () => {
analytics('compose_addattachment_camera_nopermission', {
action: 'cancel'
})
}
2021-01-19 01:13:45 +01:00
},
{
text: i18next.t(
'sharedCompose:content.root.actions.attachment.actions.photo.alert.buttons.settings'
),
style: 'default',
2021-01-24 02:25:43 +01:00
onPress: () => {
analytics('compose_addattachment_camera_nopermission', {
action: 'settings'
})
Linking.openURL('app-settings:')
}
2021-01-19 01:13:45 +01:00
}
]
)
2020-12-30 01:33:58 +01:00
} else {
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
exif: false
})
2020-12-30 00:56:25 +01:00
2020-12-30 01:33:58 +01:00
if (!result.cancelled) {
uploadAttachment(result)
}
2020-12-30 00:56:25 +01:00
}
}
}
)
}
export default addAttachment