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
|