diff options
author | Michael Staub <michael.staub@brightmachines.com> | 2023-02-23 16:34:25 -0800 |
---|---|---|
committer | Michael Staub <michael.staub@brightmachines.com> | 2023-02-23 16:34:25 -0800 |
commit | 693cbb9f18eeec48ea6ed3eb03ff3a96ca6ec7dc (patch) | |
tree | 192494fe0751aa279209f447587c311efcd33668 /src/lib/media/picker.tsx | |
parent | 23f07d8def1f4384022c7fecd0d7eac0ba8b2efc (diff) | |
parent | bbd0b03a46b1087ecca17219441d060c2be69de2 (diff) | |
download | voidsky-693cbb9f18eeec48ea6ed3eb03ff3a96ca6ec7dc.tar.zst |
Merge branch 'rnw' of github.com:bluesky-social/social-app into rnw
Diffstat (limited to 'src/lib/media/picker.tsx')
-rw-r--r-- | src/lib/media/picker.tsx | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/lib/media/picker.tsx b/src/lib/media/picker.tsx new file mode 100644 index 000000000..940366035 --- /dev/null +++ b/src/lib/media/picker.tsx @@ -0,0 +1,141 @@ +import { + openPicker as openPickerFn, + openCamera as openCameraFn, + openCropper as openCropperFn, + ImageOrVideo, +} from 'react-native-image-crop-picker' +import {RootStoreModel} from 'state/index' +import {PickerOpts, CameraOpts, CropperOpts, PickedMedia} from './types' +import { + scaleDownDimensions, + Dim, + compressIfNeeded, + moveToPremanantPath, +} from 'lib/media/manip' +export type {PickedMedia} from './types' + +/** + * NOTE + * These methods all include the RootStoreModel as the first param + * because the web versions require it. The signatures have to remain + * equivalent between the different forms, but the store param is not + * used here. + * -prf + */ + +export async function openPicker( + _store: RootStoreModel, + opts: PickerOpts, +): Promise<PickedMedia[]> { + const mediaType = opts.mediaType || 'photo' + const items = await openPickerFn({ + mediaType, + multiple: opts.multiple, + maxFiles: opts.maxFiles, + }) + const toMedia = (item: ImageOrVideo) => ({ + mediaType, + path: item.path, + mime: item.mime, + size: item.size, + width: item.width, + height: item.height, + }) + if (Array.isArray(items)) { + return items.map(toMedia) + } + return [toMedia(items)] +} + +export async function openCamera( + _store: RootStoreModel, + opts: CameraOpts, +): Promise<PickedMedia> { + const mediaType = opts.mediaType || 'photo' + const item = await openCameraFn({ + mediaType, + width: opts.width, + height: opts.height, + freeStyleCropEnabled: opts.freeStyleCropEnabled, + cropperCircleOverlay: opts.cropperCircleOverlay, + cropping: true, + forceJpg: true, // ios only + compressImageQuality: 1.0, + }) + return { + mediaType, + path: item.path, + mime: item.mime, + size: item.size, + width: item.width, + height: item.height, + } +} + +export async function openCropper( + _store: RootStoreModel, + opts: CropperOpts, +): Promise<PickedMedia> { + const mediaType = opts.mediaType || 'photo' + const item = await openCropperFn({ + path: opts.path, + mediaType: opts.mediaType || 'photo', + width: opts.width, + height: opts.height, + freeStyleCropEnabled: opts.freeStyleCropEnabled, + cropperCircleOverlay: opts.cropperCircleOverlay, + forceJpg: true, // ios only + compressImageQuality: 1.0, + }) + return { + mediaType, + path: item.path, + mime: item.mime, + size: item.size, + width: item.width, + height: item.height, + } +} + +export async function pickImagesFlow( + store: RootStoreModel, + maxFiles: number, + maxDim: Dim, + maxSize: number, +) { + const items = await openPicker(store, { + multiple: true, + maxFiles, + mediaType: 'photo', + }) + const result = [] + for (const image of items) { + result.push( + await cropAndCompressFlow(store, image.path, image, maxDim, maxSize), + ) + } + return result +} + +export async function cropAndCompressFlow( + store: RootStoreModel, + path: string, + imgDim: Dim, + maxDim: Dim, + maxSize: number, +) { + // choose target dimensions based on the original + // this causes the photo cropper to start with the full image "selected" + const {width, height} = scaleDownDimensions(imgDim, maxDim) + const cropperRes = await openCropper(store, { + mediaType: 'photo', + path, + freeStyleCropEnabled: true, + width, + height, + }) + + const img = await compressIfNeeded(cropperRes, maxSize) + const permanentPath = await moveToPremanantPath(img.path) + return permanentPath +} |