Cleanup, comments
(cherry picked from commit 6c9c98648e37257285a9c8caeb1eadcc56c81402)
This commit is contained in:
committed by
Samuel Newman
parent
81c0456794
commit
82018c1a1e
@@ -21,7 +21,7 @@ import {getVideoMetadata} from '#/view/com/composer/videos/pickVideo'
|
|||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import {useSheetWrapper} from '#/components/Dialog/sheet-wrapper'
|
import {useSheetWrapper} from '#/components/Dialog/sheet-wrapper'
|
||||||
import {Image_Stroke2_Corner0_Rounded as Image} from '#/components/icons/Image'
|
import {Image_Stroke2_Corner0_Rounded as ImageIcon} from '#/components/icons/Image'
|
||||||
import {toast} from '#/components/Toast'
|
import {toast} from '#/components/Toast'
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
@@ -30,22 +30,28 @@ export type Props = {
|
|||||||
setError: (error: string) => void
|
setError: (error: string) => void
|
||||||
selectedAssetsCount: number
|
selectedAssetsCount: number
|
||||||
onSelectAssets: (props: {
|
onSelectAssets: (props: {
|
||||||
type: SelectedAsset['type']
|
type: AssetType
|
||||||
assets: ImagePickerAsset[]
|
assets: ImagePickerAsset[]
|
||||||
errors: string[]
|
errors: string[]
|
||||||
}) => void
|
}) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SelectedAsset = {
|
/**
|
||||||
asset: ImagePickerAsset
|
* Generic asset classes, or buckets, that we support.
|
||||||
type: 'video' | 'image' | 'gif'
|
*/
|
||||||
}
|
type AssetType = 'video' | 'image' | 'gif'
|
||||||
|
|
||||||
export type ValidatedImagePickerAsset = Omit<ImagePickerAsset, 'mimeType'> & {
|
/**
|
||||||
|
* Shadows `ImagePickerAsset` from `expo-image-picker`, but with a guaranteed `mimeType`
|
||||||
|
*/
|
||||||
|
type ValidatedImagePickerAsset = Omit<ImagePickerAsset, 'mimeType'> & {
|
||||||
mimeType: string
|
mimeType: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SelectedAssetError {
|
/**
|
||||||
|
* Codes for known validation states
|
||||||
|
*/
|
||||||
|
enum SelectedAssetError {
|
||||||
Unsupported = 'Unsupported',
|
Unsupported = 'Unsupported',
|
||||||
MixedTypes = 'MixedTypes',
|
MixedTypes = 'MixedTypes',
|
||||||
MaxImages = 'MaxImages',
|
MaxImages = 'MaxImages',
|
||||||
@@ -55,20 +61,27 @@ export enum SelectedAssetError {
|
|||||||
NoGifsOnNative = 'NoGifsOnNative',
|
NoGifsOnNative = 'NoGifsOnNative',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported video mime types. This differs slightly from
|
||||||
|
* `SUPPORTED_MIME_TYPES` from `#/lib/constants` because we only care about
|
||||||
|
* videos here.
|
||||||
|
*/
|
||||||
const SUPPORTED_VIDEO_MIME_TYPES = [
|
const SUPPORTED_VIDEO_MIME_TYPES = [
|
||||||
'video/mp4',
|
'video/mp4',
|
||||||
'video/mpeg',
|
'video/mpeg',
|
||||||
'video/webm',
|
'video/webm',
|
||||||
'video/quicktime',
|
'video/quicktime',
|
||||||
] as const
|
] as const
|
||||||
export type SupportedVideoMimeType = (typeof SUPPORTED_VIDEO_MIME_TYPES)[number]
|
type SupportedVideoMimeType = (typeof SUPPORTED_VIDEO_MIME_TYPES)[number]
|
||||||
|
|
||||||
function isSupportedVideoMimeType(
|
function isSupportedVideoMimeType(
|
||||||
mimeType: string,
|
mimeType: string,
|
||||||
): mimeType is SupportedVideoMimeType {
|
): mimeType is SupportedVideoMimeType {
|
||||||
return SUPPORTED_VIDEO_MIME_TYPES.includes(mimeType as SupportedVideoMimeType)
|
return SUPPORTED_VIDEO_MIME_TYPES.includes(mimeType as SupportedVideoMimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported image mime types.
|
||||||
|
*/
|
||||||
const SUPPORTED_IMAGE_MIME_TYPES = (
|
const SUPPORTED_IMAGE_MIME_TYPES = (
|
||||||
[
|
[
|
||||||
'image/gif',
|
'image/gif',
|
||||||
@@ -79,17 +92,19 @@ const SUPPORTED_IMAGE_MIME_TYPES = (
|
|||||||
isIOS && 'image/heic',
|
isIOS && 'image/heic',
|
||||||
] as const
|
] as const
|
||||||
).filter(Boolean)
|
).filter(Boolean)
|
||||||
export type SupportedImageMimeType = Exclude<
|
type SupportedImageMimeType = Exclude<
|
||||||
(typeof SUPPORTED_IMAGE_MIME_TYPES)[number],
|
(typeof SUPPORTED_IMAGE_MIME_TYPES)[number],
|
||||||
boolean
|
boolean
|
||||||
>
|
>
|
||||||
|
|
||||||
function isSupportedImageMimeType(
|
function isSupportedImageMimeType(
|
||||||
mimeType: string,
|
mimeType: string,
|
||||||
): mimeType is SupportedImageMimeType {
|
): mimeType is SupportedImageMimeType {
|
||||||
return SUPPORTED_IMAGE_MIME_TYPES.includes(mimeType as SupportedImageMimeType)
|
return SUPPORTED_IMAGE_MIME_TYPES.includes(mimeType as SupportedImageMimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a last-ditch effort type thing here, try not to rely on this.
|
||||||
|
*/
|
||||||
const extensionToMimeType: Record<
|
const extensionToMimeType: Record<
|
||||||
string,
|
string,
|
||||||
SupportedVideoMimeType | SupportedImageMimeType
|
SupportedVideoMimeType | SupportedImageMimeType
|
||||||
@@ -97,6 +112,7 @@ const extensionToMimeType: Record<
|
|||||||
mp4: 'video/mp4',
|
mp4: 'video/mp4',
|
||||||
mov: 'video/quicktime',
|
mov: 'video/quicktime',
|
||||||
webm: 'video/webm',
|
webm: 'video/webm',
|
||||||
|
webp: 'image/webp',
|
||||||
gif: 'image/gif',
|
gif: 'image/gif',
|
||||||
jpg: 'image/jpeg',
|
jpg: 'image/jpeg',
|
||||||
jpeg: 'image/jpeg',
|
jpeg: 'image/jpeg',
|
||||||
@@ -105,10 +121,15 @@ const extensionToMimeType: Record<
|
|||||||
heic: 'image/heic',
|
heic: 'image/heic',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attemps to bucket the given asset into one of our known types based on its
|
||||||
|
* `mimeType`. If `mimeType` is not available, we try to infer it through
|
||||||
|
* various means.
|
||||||
|
*/
|
||||||
function classifyImagePickerAsset(asset: ImagePickerAsset):
|
function classifyImagePickerAsset(asset: ImagePickerAsset):
|
||||||
| {
|
| {
|
||||||
success: true
|
success: true
|
||||||
type: SelectedAsset['type']
|
type: AssetType
|
||||||
mimeType: string
|
mimeType: string
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -153,7 +174,7 @@ function classifyImagePickerAsset(asset: ImagePickerAsset):
|
|||||||
/*
|
/*
|
||||||
* Distill this down into a type "class".
|
* Distill this down into a type "class".
|
||||||
*/
|
*/
|
||||||
let type: SelectedAsset['type'] | undefined
|
let type: AssetType | undefined
|
||||||
if (mimeType === 'image/gif') {
|
if (mimeType === 'image/gif') {
|
||||||
type = 'gif'
|
type = 'gif'
|
||||||
} else if (mimeType?.startsWith('video/')) {
|
} else if (mimeType?.startsWith('video/')) {
|
||||||
@@ -187,8 +208,9 @@ function classifyImagePickerAsset(asset: ImagePickerAsset):
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On web, certain file formats (like `.mov`) don't give us a duration or
|
* WEB ONLY. On web, certain file formats (like `.mov`) don't give us a
|
||||||
* dimensions, so we need to load the file manually to extract this.
|
* duration or dimensions, so we need to load the file manually to extract
|
||||||
|
* this.
|
||||||
*/
|
*/
|
||||||
async function getAdditionalVideoMetadata(asset: ValidatedImagePickerAsset) {
|
async function getAdditionalVideoMetadata(asset: ValidatedImagePickerAsset) {
|
||||||
if (isNative) return asset
|
if (isNative) return asset
|
||||||
@@ -203,6 +225,11 @@ async function getAdditionalVideoMetadata(asset: ValidatedImagePickerAsset) {
|
|||||||
return await getVideoMetadata(file)
|
return await getVideoMetadata(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes in raw assets from `expo-image-picker` and applies validation. Returns
|
||||||
|
* the dominant `AssetType`, any valid assets, and any errors encountered along
|
||||||
|
* the way.
|
||||||
|
*/
|
||||||
async function processImagePickerAssets(
|
async function processImagePickerAssets(
|
||||||
assets: ImagePickerAsset[],
|
assets: ImagePickerAsset[],
|
||||||
{
|
{
|
||||||
@@ -220,7 +247,7 @@ async function processImagePickerAssets(
|
|||||||
* We only support selecting a single type of media at a time, so this
|
* We only support selecting a single type of media at a time, so this
|
||||||
* gets set to whatever the first asset type is.
|
* gets set to whatever the first asset type is.
|
||||||
*/
|
*/
|
||||||
let primaryMediaType: SelectedAsset['type'] | undefined
|
let primaryMediaType: AssetType | undefined
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will hold the assets that we can actually use, after filtering
|
* This will hold the assets that we can actually use, after filtering
|
||||||
@@ -452,7 +479,7 @@ export function SelectMediaBtn({
|
|||||||
shape="round"
|
shape="round"
|
||||||
color="primary"
|
color="primary"
|
||||||
disabled={disabled}>
|
disabled={disabled}>
|
||||||
<Image
|
<ImageIcon
|
||||||
size="lg"
|
size="lg"
|
||||||
style={disabled && t.atoms.text_contrast_low}
|
style={disabled && t.atoms.text_contrast_low}
|
||||||
accessibilityIgnoresInvertColors={true}
|
accessibilityIgnoresInvertColors={true}
|
||||||
|
|||||||
Reference in New Issue
Block a user