mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Prepare for future media needs
NOT USED
This commit is contained in:
		
							
								
								
									
										149
									
								
								src/components/mediaTransformation.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/components/mediaTransformation.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| import { store } from '@root/store' | ||||
| import { getInstanceConfigurationMediaAttachments } from '@utils/slices/instancesSlice' | ||||
| import { Action, manipulateAsync, SaveFormat } from 'expo-image-manipulator' | ||||
| import i18next from 'i18next' | ||||
| import { Platform } from 'react-native' | ||||
| import ImagePicker from 'react-native-image-crop-picker' | ||||
|  | ||||
| export interface Props { | ||||
|   type: 'image' | 'video' | ||||
|   uri: string // This can be pure path or uri starting with file:// | ||||
|   mime?: string | ||||
|   transform: { | ||||
|     imageFormat?: SaveFormat.JPEG | SaveFormat.PNG | ||||
|     resize?: boolean | ||||
|     width?: number | ||||
|     height?: number | ||||
|   } | ||||
| } | ||||
|  | ||||
| const getFileExtension = (uri: string) => { | ||||
|   const extension = uri.split('.').pop() | ||||
|   // Using mime type standard of jpeg | ||||
|   return extension === 'jpg' ? 'jpeg' : extension | ||||
| } | ||||
|  | ||||
| const mediaTransformation = async ({ | ||||
|   type, | ||||
|   uri, | ||||
|   mime, | ||||
|   transform | ||||
| }: Props): Promise<{ | ||||
|   uri: string | ||||
|   mime: string | ||||
|   width: number | ||||
|   height: number | ||||
| }> => { | ||||
|   const configurationMediaAttachments = | ||||
|     getInstanceConfigurationMediaAttachments(store.getState()) | ||||
|  | ||||
|   const fileExtension = getFileExtension(uri) | ||||
|  | ||||
|   switch (type) { | ||||
|     case 'image': | ||||
|       if (mime === 'image/gif' || fileExtension === 'gif') { | ||||
|         return Promise.reject('GIFs should not be transformed') | ||||
|       } | ||||
|       let targetFormat: SaveFormat.JPEG | SaveFormat.PNG = SaveFormat.JPEG | ||||
|  | ||||
|       const supportedImageTypes = | ||||
|         configurationMediaAttachments.supported_mime_types.filter(mime => | ||||
|           mime.startsWith('image/') | ||||
|         ) | ||||
|  | ||||
|       // @ts-ignore | ||||
|       const transformations: Action[] = [ | ||||
|         !transform.resize && (transform.width || transform.height) | ||||
|           ? { | ||||
|               resize: { width: transform.width, height: transform.height } | ||||
|             } | ||||
|           : null | ||||
|       ].filter(t => !!t) | ||||
|  | ||||
|       if (mime) { | ||||
|         if ( | ||||
|           mime !== `image/${fileExtension}` || | ||||
|           !supportedImageTypes.includes(mime) | ||||
|         ) { | ||||
|           targetFormat = transform.imageFormat || SaveFormat.JPEG | ||||
|         } else { | ||||
|           targetFormat = mime.split('/').pop() as any | ||||
|         } | ||||
|       } else { | ||||
|         if (!fileExtension) { | ||||
|           return Promise.reject('Unable to get file extension') | ||||
|         } | ||||
|         if (!supportedImageTypes.includes(`image/${fileExtension}`)) { | ||||
|           targetFormat = transform.imageFormat || SaveFormat.JPEG | ||||
|         } else { | ||||
|           targetFormat = fileExtension as any | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       const converted = await manipulateAsync(uri, transformations, { | ||||
|         base64: false, | ||||
|         compress: Platform.OS === 'ios' ? 0.8 : 1, | ||||
|         format: targetFormat | ||||
|       }) | ||||
|  | ||||
|       if (transform.resize) { | ||||
|         const resized = await ImagePicker.openCropper({ | ||||
|           mediaType: 'photo', | ||||
|           path: converted.uri, | ||||
|           width: transform.width, | ||||
|           height: transform.height, | ||||
|           cropperChooseText: i18next.t('common:buttons.apply'), | ||||
|           cropperCancelText: i18next.t('common:buttons.cancel'), | ||||
|           hideBottomControls: true | ||||
|         }) | ||||
|         if (!resized) { | ||||
|           return Promise.reject('Resize failed') | ||||
|         } else { | ||||
|           return { | ||||
|             uri: resized.path, | ||||
|             mime: resized.mime, | ||||
|             width: resized.width, | ||||
|             height: resized.height | ||||
|           } | ||||
|         } | ||||
|       } else { | ||||
|         return { | ||||
|           uri: converted.uri, | ||||
|           mime: transform.imageFormat || SaveFormat.JPEG, | ||||
|           width: converted.width, | ||||
|           height: converted.height | ||||
|         } | ||||
|       } | ||||
|     case 'video': | ||||
|       const supportedVideoTypes = | ||||
|         configurationMediaAttachments.supported_mime_types.filter(mime => | ||||
|           mime.startsWith('video/') | ||||
|         ) | ||||
|  | ||||
|       if (mime) { | ||||
|         if (mime !== `video/${fileExtension}`) { | ||||
|           console.warn('Video mime type and file extension does not match') | ||||
|         } | ||||
|         if (!supportedVideoTypes.includes(mime)) { | ||||
|           return Promise.reject('Video file type is not supported') | ||||
|         } | ||||
|       } else { | ||||
|         if (!fileExtension) { | ||||
|           return Promise.reject('Unable to get file extension') | ||||
|         } | ||||
|         if (!supportedVideoTypes.includes(`video/${fileExtension}`)) { | ||||
|           return Promise.reject('Video file type is not supported') | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       return { | ||||
|         uri: uri, | ||||
|         mime: mime || `video/${fileExtension}`, | ||||
|         width: 0, | ||||
|         height: 0 | ||||
|       } | ||||
|       break | ||||
|   } | ||||
| } | ||||
|  | ||||
| export default mediaTransformation | ||||
| @@ -381,6 +381,43 @@ export const getInstanceConfigurationStatusCharsURL = ({ | ||||
|   instances[findInstanceActive(instances)]?.configuration?.statuses | ||||
|     .characters_reserved_per_url || 23 | ||||
|  | ||||
| export const getInstanceConfigurationMediaAttachments = ({ | ||||
|   instances: { instances } | ||||
| }: RootState) => | ||||
|   instances[findInstanceActive(instances)]?.configuration | ||||
|     ?.media_attachments || { | ||||
|     supported_mime_types: [ | ||||
|       'image/jpeg', | ||||
|       'image/png', | ||||
|       'image/gif', | ||||
|       'video/webm', | ||||
|       'video/mp4', | ||||
|       'video/quicktime', | ||||
|       'video/ogg', | ||||
|       'audio/wave', | ||||
|       'audio/wav', | ||||
|       'audio/x-wav', | ||||
|       'audio/x-pn-wave', | ||||
|       'audio/ogg', | ||||
|       'audio/vorbis', | ||||
|       'audio/mpeg', | ||||
|       'audio/mp3', | ||||
|       'audio/webm', | ||||
|       'audio/flac', | ||||
|       'audio/aac', | ||||
|       'audio/m4a', | ||||
|       'audio/x-m4a', | ||||
|       'audio/mp4', | ||||
|       'audio/3gpp', | ||||
|       'video/x-ms-asf' | ||||
|     ], | ||||
|     image_size_limit: 10485760, | ||||
|     image_matrix_limit: 16777216, | ||||
|     video_size_limit: 41943040, | ||||
|     video_frame_rate_limit: 60, | ||||
|     video_matrix_limit: 2304000 | ||||
|   } | ||||
|  | ||||
| export const getInstanceConfigurationPoll = ({ | ||||
|   instances: { instances } | ||||
| }: RootState) => | ||||
|   | ||||
		Reference in New Issue
	
	Block a user