diff --git a/lib/types/media-types.js b/lib/types/media-types.js --- a/lib/types/media-types.js +++ b/lib/types/media-types.js @@ -215,7 +215,7 @@ +dimensions: Dimensions, +filename: ?string, +uri: string, - +mediaNativeID: string, + +mediaNativeID: ?string, +selectTime: number, // ms timestamp +sendTime: number, // ms timestamp +retries: number, @@ -225,7 +225,7 @@ +dimensions: Dimensions, +filename: ?string, +uri: string, - +mediaNativeID: string, + +mediaNativeID: ?string, +selectTime: number, // ms timestamp +sendTime: number, // ms timestamp +retries: number, diff --git a/native/media/media-gallery-keyboard.react.js b/native/media/media-gallery-keyboard.react.js --- a/native/media/media-gallery-keyboard.react.js +++ b/native/media/media-gallery-keyboard.react.js @@ -1,5 +1,6 @@ // @flow +import * as ImagePicker from 'expo-image-picker'; import * as MediaLibrary from 'expo-media-library'; import invariant from 'invariant'; import * as React from 'react'; @@ -15,7 +16,10 @@ import { KeyboardRegistry } from 'react-native-keyboard-input'; import { Provider } from 'react-redux'; -import { extensionFromFilename } from 'lib/media/file-utils'; +import { + extensionFromFilename, + filenameFromPathOrURI, +} from 'lib/media/file-utils'; import { useIsAppForegrounded } from 'lib/shared/lifecycle-utils'; import type { MediaLibrarySelection } from 'lib/types/media-types'; @@ -278,6 +282,85 @@ this.fetchingPhotos = false; } + openNativePicker = async () => { + try { + const { assets, canceled } = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.All, + allowsEditing: false, + allowsMultipleSelection: true, + // maximum quality is 1 - it disables compression + quality: 1, + // we don't want to compress videos at this point + videoExportPreset: ImagePicker.VideoExportPreset.Passthrough, + }); + + if (canceled || assets.length === 0) { + return; + } + + const selections = assets.map(asset => { + const { + width, + height, + fileName, + type, + duration, + assetId: mediaNativeID, + } = asset; + const isVideo = type === 'video'; + const filename = fileName || filenameFromPathOrURI(asset.uri) || ''; + const uri = getCompatibleMediaURI( + asset.uri, + extensionFromFilename(filename), + ); + + if (isVideo) { + return { + step: 'video_library', + dimensions: { height, width }, + uri, + filename, + mediaNativeID, + duration, + selectTime: 0, + sendTime: 0, + retries: 0, + }; + } else { + return { + step: 'photo_library', + dimensions: { height, width }, + uri, + filename, + mediaNativeID, + selectTime: 0, + sendTime: 0, + retries: 0, + }; + } + }); + + const selectionURIs = selections.map(({ uri }) => uri); + this.guardedSetState(prevState => ({ + error: null, + selections: [...selections, ...(prevState.selections ?? [])], + queuedMediaURIs: new Set([ + ...selectionURIs, + ...(prevState.queuedMediaURIs ?? []), + ]), + focusedMediaURI: null, + })); + } catch (e) { + if (__DEV__) { + console.warn(e); + } + this.guardedSetState({ + selections: null, + error: 'something went wrong :(', + }); + } + }; + async getPermissions(): Promise { const { granted } = await MediaLibrary.requestPermissionsAsync(); if (!granted) {