Use expo-image-picker on Web (#847)
parent
a67eaa6ace
commit
bdcdb4e4dc
|
@ -0,0 +1,23 @@
|
||||||
|
import {
|
||||||
|
ImagePickerOptions,
|
||||||
|
launchImageLibraryAsync,
|
||||||
|
MediaTypeOptions,
|
||||||
|
} from 'expo-image-picker'
|
||||||
|
import {getDataUriSize} from './util'
|
||||||
|
|
||||||
|
export async function openPicker(opts?: ImagePickerOptions) {
|
||||||
|
const response = await launchImageLibraryAsync({
|
||||||
|
exif: false,
|
||||||
|
mediaTypes: MediaTypeOptions.Images,
|
||||||
|
quality: 1,
|
||||||
|
...opts,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (response.assets ?? []).map(image => ({
|
||||||
|
mime: 'image/jpeg',
|
||||||
|
height: image.height,
|
||||||
|
width: image.width,
|
||||||
|
path: image.uri,
|
||||||
|
size: getDataUriSize(image.uri),
|
||||||
|
}))
|
||||||
|
}
|
|
@ -5,12 +5,7 @@ import {
|
||||||
} from 'react-native-image-crop-picker'
|
} from 'react-native-image-crop-picker'
|
||||||
import {RootStoreModel} from 'state/index'
|
import {RootStoreModel} from 'state/index'
|
||||||
import {CameraOpts, CropperOptions} from './types'
|
import {CameraOpts, CropperOptions} from './types'
|
||||||
import {
|
export {openPicker} from './picker.shared'
|
||||||
ImagePickerOptions,
|
|
||||||
launchImageLibraryAsync,
|
|
||||||
MediaTypeOptions,
|
|
||||||
} from 'expo-image-picker'
|
|
||||||
import {getDataUriSize} from './util'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE
|
* NOTE
|
||||||
|
@ -21,26 +16,6 @@ import {getDataUriSize} from './util'
|
||||||
* -prf
|
* -prf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export async function openPicker(
|
|
||||||
_store: RootStoreModel,
|
|
||||||
opts?: ImagePickerOptions,
|
|
||||||
) {
|
|
||||||
const response = await launchImageLibraryAsync({
|
|
||||||
exif: false,
|
|
||||||
mediaTypes: MediaTypeOptions.Images,
|
|
||||||
quality: 1,
|
|
||||||
...opts,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (response.assets ?? []).map(image => ({
|
|
||||||
mime: 'image/jpeg',
|
|
||||||
height: image.height,
|
|
||||||
width: image.width,
|
|
||||||
path: image.uri,
|
|
||||||
size: getDataUriSize(image.uri),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function openCamera(
|
export async function openCamera(
|
||||||
_store: RootStoreModel,
|
_store: RootStoreModel,
|
||||||
opts: CameraOpts,
|
opts: CameraOpts,
|
||||||
|
|
|
@ -1,34 +1,9 @@
|
||||||
/// <reference lib="dom" />
|
/// <reference lib="dom" />
|
||||||
|
|
||||||
import {PickerOpts, CameraOpts, CropperOptions} from './types'
|
import {CameraOpts, CropperOptions} from './types'
|
||||||
import {RootStoreModel} from 'state/index'
|
import {RootStoreModel} from 'state/index'
|
||||||
import {getImageDim} from 'lib/media/manip'
|
|
||||||
import {extractDataUriMime} from './util'
|
|
||||||
import {Image as RNImage} from 'react-native-image-crop-picker'
|
import {Image as RNImage} from 'react-native-image-crop-picker'
|
||||||
|
export {openPicker} from './picker.shared'
|
||||||
interface PickedFile {
|
|
||||||
uri: string
|
|
||||||
path: string
|
|
||||||
size: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function openPicker(
|
|
||||||
_store: RootStoreModel,
|
|
||||||
opts?: PickerOpts,
|
|
||||||
): Promise<RNImage[]> {
|
|
||||||
const res = await selectFile(opts)
|
|
||||||
const dim = await getImageDim(res.uri)
|
|
||||||
const mime = extractDataUriMime(res.uri)
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
path: res.uri,
|
|
||||||
mime,
|
|
||||||
size: res.size,
|
|
||||||
width: dim.width,
|
|
||||||
height: dim.height,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function openCamera(
|
export async function openCamera(
|
||||||
_store: RootStoreModel,
|
_store: RootStoreModel,
|
||||||
|
@ -57,44 +32,3 @@ export async function openCropper(
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the select file dialog in the browser.
|
|
||||||
* NOTE:
|
|
||||||
* If in the future someone updates this method to use:
|
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker
|
|
||||||
* Check that the `showOpenFilePicker` API does not require any permissions
|
|
||||||
* granted to use. As of this writing, it does not, but that could change
|
|
||||||
* in the future. If the user does need to go through a permissions granting
|
|
||||||
* flow, then checkout the usePhotoLibraryPermission() hook in
|
|
||||||
* src/lib/hooks/usePermissions.ts
|
|
||||||
* so that it gets appropriately updated.
|
|
||||||
*/
|
|
||||||
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()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ export class GalleryModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
async pick() {
|
async pick() {
|
||||||
const images = await openPicker(this.rootStore, {
|
const images = await openPicker({
|
||||||
selectionLimit: 4 - this.size,
|
selectionLimit: 4 - this.size,
|
||||||
allowsMultipleSelection: true,
|
allowsMultipleSelection: true,
|
||||||
})
|
})
|
||||||
|
|
|
@ -147,7 +147,7 @@ export function UserAvatar({
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = await openPicker(store, {
|
const items = await openPicker({
|
||||||
aspect: [1, 1],
|
aspect: [1, 1],
|
||||||
})
|
})
|
||||||
const item = items[0]
|
const item = items[0]
|
||||||
|
|
|
@ -55,7 +55,7 @@ export function UserBanner({
|
||||||
if (!(await requestPhotoAccessIfNeeded())) {
|
if (!(await requestPhotoAccessIfNeeded())) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const items = await openPicker(store)
|
const items = await openPicker()
|
||||||
|
|
||||||
onSelectNewBanner?.(
|
onSelectNewBanner?.(
|
||||||
await openCropper(store, {
|
await openCropper(store, {
|
||||||
|
|
Loading…
Reference in New Issue