diff options
Diffstat (limited to 'src/view/com/util/images')
5 files changed, 198 insertions, 38 deletions
diff --git a/src/view/com/util/images/ImageCropPicker.tsx b/src/view/com/util/images/ImageCropPicker.tsx deleted file mode 100644 index 9cd4da9f5..000000000 --- a/src/view/com/util/images/ImageCropPicker.tsx +++ /dev/null @@ -1,6 +0,0 @@ -export { - openPicker, - openCamera, - openCropper, -} from 'react-native-image-crop-picker' -export type {Image} from 'react-native-image-crop-picker' diff --git a/src/view/com/util/images/ImageCropPicker.web.tsx b/src/view/com/util/images/ImageCropPicker.web.tsx deleted file mode 100644 index a385e2e93..000000000 --- a/src/view/com/util/images/ImageCropPicker.web.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type { - Image, - Video, - ImageOrVideo, - Options, - PossibleArray, -} from 'react-native-image-crop-picker' - -export type {Image} from 'react-native-image-crop-picker' - -type MediaType<O> = O extends {mediaType: 'photo'} - ? Image - : O extends {mediaType: 'video'} - ? Video - : ImageOrVideo - -export async function openPicker<O extends Options>( - _options: O, -): Promise<PossibleArray<O, MediaType<O>>> { - // TODO - throw new Error('TODO') -} -export async function openCamera<O extends Options>( - _options: O, -): Promise<PossibleArray<O, MediaType<O>>> { - // TODO - throw new Error('TODO') -} -export async function openCropper(_options: Options): Promise<Image> { - // TODO - throw new Error('TODO') -} diff --git a/src/view/com/util/images/image-crop-picker/ImageCropPicker.tsx b/src/view/com/util/images/image-crop-picker/ImageCropPicker.tsx new file mode 100644 index 000000000..ddc9e87fd --- /dev/null +++ b/src/view/com/util/images/image-crop-picker/ImageCropPicker.tsx @@ -0,0 +1,92 @@ +import { + openPicker as openPickerFn, + openCamera as openCameraFn, + openCropper as openCropperFn, + ImageOrVideo, +} from 'react-native-image-crop-picker' +import {RootStoreModel} from '../../../../../state' +import {PickerOpts, CameraOpts, CropperOpts, PickedMedia} from './types' +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, + } +} diff --git a/src/view/com/util/images/image-crop-picker/ImageCropPicker.web.tsx b/src/view/com/util/images/image-crop-picker/ImageCropPicker.web.tsx new file mode 100644 index 000000000..a7037f3a4 --- /dev/null +++ b/src/view/com/util/images/image-crop-picker/ImageCropPicker.web.tsx @@ -0,0 +1,75 @@ +/// <reference lib="dom" /> + +import {CropImageModal} from '../../../../../state/models/shell-ui' +import {PickerOpts, CameraOpts, CropperOpts, PickedMedia} from './types' +export type {PickedMedia} from './types' +import {RootStoreModel} from '../../../../../state' + +interface PickedFile { + uri: string + path: string + size: number +} + +export async function openPicker( + store: RootStoreModel, + opts: PickerOpts, +): Promise<PickedMedia[] | PickedMedia> { + const res = await selectFile(opts) + return new Promise((resolve, reject) => { + store.shell.openModal( + new CropImageModal(res.uri, (img?: PickedMedia) => { + if (img) { + resolve(img) + } else { + reject(new Error('Canceled')) + } + }), + ) + }) +} + +export async function openCamera( + _store: RootStoreModel, + opts: CameraOpts, +): Promise<PickedMedia> { + const mediaType = opts.mediaType || 'photo' + throw new Error('TODO') +} + +export async function openCropper( + _store: RootStoreModel, + opts: CropperOpts, +): Promise<PickedMedia> { + const mediaType = opts.mediaType || 'photo' + throw new Error('TODO') +} + +function selectFile(opts: PickerOpts): Promise<PickedFile> { + return new Promise((resolve, reject) => { + var input = document.createElement('input') + input.type = 'file' + input.accept = opts.mediaType === 'photo' ? 'image/*' : '*/*' + input.onchange = e => { + const target = e.target as HTMLInputElement + const file = target?.files?.[0] + if (!file) { + return reject(new Error('Canceled')) + } + + var reader = new FileReader() + reader.readAsDataURL(file) + reader.onload = readerEvent => { + if (!readerEvent.target) { + return reject(new Error('Canceled')) + } + resolve({ + uri: readerEvent.target.result as string, + path: file.name, + size: file.size, + }) + } + } + input.click() + }) +} diff --git a/src/view/com/util/images/image-crop-picker/types.ts b/src/view/com/util/images/image-crop-picker/types.ts new file mode 100644 index 000000000..3197b4d3e --- /dev/null +++ b/src/view/com/util/images/image-crop-picker/types.ts @@ -0,0 +1,31 @@ +export interface PickerOpts { + mediaType?: 'photo' + multiple?: boolean + maxFiles?: number +} + +export interface CameraOpts { + mediaType?: 'photo' + width: number + height: number + freeStyleCropEnabled?: boolean + cropperCircleOverlay?: boolean +} + +export interface CropperOpts { + path: string + mediaType?: 'photo' + width: number + height: number + freeStyleCropEnabled?: boolean + cropperCircleOverlay?: boolean +} + +export interface PickedMedia { + mediaType: 'photo' + path: string + mime: string + size: number + width: number + height: number +} |