expo-image-picker 16.0.2 → 16.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 16.0.3 — 2024-11-22
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 16.0.2 — 2024-11-14
14
18
 
15
19
  _This version does not introduce any user-facing changes._
@@ -97,6 +101,7 @@ _This version does not introduce any user-facing changes._
97
101
  ### 🐛 Bug fixes
98
102
 
99
103
  - On Android `fileSize` was named `filesize` which did not match the docs & typescript definition. ([#27293](https://github.com/expo/expo/pull/27293) by [@WookieFPV](https://github.com/wookieFPV))
104
+ - Fixed cancelled picker dialog not resolving with expected result on web. ([#11847](https://github.com/expo/expo/pull/27454) by [@raqso](https://github.com/raqso))
100
105
 
101
106
  ### 💡 Others
102
107
 
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'host.exp.exponent'
4
- version = '16.0.2'
4
+ version = '16.0.3'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -14,7 +14,7 @@ android {
14
14
  namespace "expo.modules.imagepicker"
15
15
  defaultConfig {
16
16
  versionCode 22
17
- versionName "16.0.2"
17
+ versionName "16.0.3"
18
18
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19
19
  }
20
20
  testOptions {
@@ -66,6 +66,7 @@ function openFileBrowserAsync({ mediaTypes, capture = false, allowsMultipleSelec
66
66
  input.setAttribute('type', 'file');
67
67
  input.setAttribute('accept', mediaTypeFormat);
68
68
  input.setAttribute('id', String(Math.random()));
69
+ input.setAttribute('data-testid', 'file-input');
69
70
  if (allowsMultipleSelection) {
70
71
  input.setAttribute('multiple', 'multiple');
71
72
  }
@@ -75,7 +76,7 @@ function openFileBrowserAsync({ mediaTypes, capture = false, allowsMultipleSelec
75
76
  document.body.appendChild(input);
76
77
  return new Promise((resolve) => {
77
78
  input.addEventListener('change', async () => {
78
- if (input.files) {
79
+ if (input.files?.length) {
79
80
  const files = allowsMultipleSelection ? input.files : [input.files[0]];
80
81
  const assets = await Promise.all(Array.from(files).map((file) => readFile(file, { base64 })));
81
82
  resolve({ canceled: false, assets });
@@ -85,6 +86,9 @@ function openFileBrowserAsync({ mediaTypes, capture = false, allowsMultipleSelec
85
86
  }
86
87
  document.body.removeChild(input);
87
88
  });
89
+ input.addEventListener('cancel', () => {
90
+ input.dispatchEvent(new Event('change'));
91
+ });
88
92
  const event = new MouseEvent('click');
89
93
  input.dispatchEvent(event);
90
94
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ExponentImagePicker.web.js","sourceRoot":"","sources":["../src/ExponentImagePicker.web.ts"],"names":[],"mappings":"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","sourcesContent":["import { PermissionResponse, PermissionStatus, Platform } from 'expo-modules-core';\n\nimport {\n ImagePickerAsset,\n ImagePickerResult,\n MediaType,\n MediaTypeOptions,\n OpenFileBrowserOptions,\n} from './ImagePicker.types';\nimport { parseMediaTypes } from './utils';\n\nconst MediaTypeInput: Record<MediaType, string> = {\n images: 'image/*',\n videos: 'video/mp4,video/quicktime,video/x-m4v,video/*',\n livePhotos: '',\n};\n\nexport default {\n async launchImageLibraryAsync({\n mediaTypes = ['images'] as MediaType[],\n allowsMultipleSelection = false,\n base64 = false,\n }): Promise<ImagePickerResult> {\n // SSR guard\n if (!Platform.isDOMAvailable) {\n return { canceled: true, assets: null };\n }\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n base64,\n });\n },\n\n async launchCameraAsync({\n mediaTypes = MediaTypeOptions.Images,\n allowsMultipleSelection = false,\n base64 = false,\n }): Promise<ImagePickerResult> {\n // SSR guard\n if (!Platform.isDOMAvailable) {\n return { canceled: true, assets: null };\n }\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n capture: true,\n base64,\n });\n },\n\n /*\n * Delegate to expo-permissions to request camera permissions\n */\n async getCameraPermissionsAsync() {\n return permissionGrantedResponse();\n },\n async requestCameraPermissionsAsync() {\n return permissionGrantedResponse();\n },\n\n /*\n * Camera roll permissions don't need to be requested on web, so we always\n * respond with granted.\n */\n async getMediaLibraryPermissionsAsync(_writeOnly: boolean) {\n return permissionGrantedResponse();\n },\n async requestMediaLibraryPermissionsAsync(_writeOnly: boolean): Promise<PermissionResponse> {\n return permissionGrantedResponse();\n },\n};\n\nfunction permissionGrantedResponse(): PermissionResponse {\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n granted: true,\n canAskAgain: true,\n };\n}\n\nfunction openFileBrowserAsync({\n mediaTypes,\n capture = false,\n allowsMultipleSelection = false,\n base64,\n}: OpenFileBrowserOptions): Promise<ImagePickerResult> {\n const parsedMediaTypes = parseMediaTypes(mediaTypes);\n\n const mediaTypeFormat = createMediaTypeFormat(parsedMediaTypes);\n\n const input = document.createElement('input');\n input.style.display = 'none';\n input.setAttribute('type', 'file');\n input.setAttribute('accept', mediaTypeFormat);\n input.setAttribute('id', String(Math.random()));\n if (allowsMultipleSelection) {\n input.setAttribute('multiple', 'multiple');\n }\n if (capture) {\n input.setAttribute('capture', 'camera');\n }\n document.body.appendChild(input);\n\n return new Promise((resolve) => {\n input.addEventListener('change', async () => {\n if (input.files) {\n const files = allowsMultipleSelection ? input.files : [input.files[0]];\n const assets: ImagePickerAsset[] = await Promise.all(\n Array.from(files).map((file) => readFile(file, { base64 }))\n );\n\n resolve({ canceled: false, assets });\n } else {\n resolve({ canceled: true, assets: null });\n }\n document.body.removeChild(input);\n });\n\n const event = new MouseEvent('click');\n input.dispatchEvent(event);\n });\n}\n\nfunction readFile(targetFile: File, options: { base64: boolean }): Promise<ImagePickerAsset> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => {\n reject(new Error(`Failed to read the selected media because the operation failed.`));\n };\n reader.onload = ({ target }) => {\n const uri = (target as any).result;\n const returnRaw = () => resolve({ uri, width: 0, height: 0 });\n const returnMediaData = (data: ImagePickerAsset) => {\n resolve({\n ...data,\n ...(options.base64 && { base64: uri.substr(uri.indexOf(',') + 1) }),\n file: targetFile,\n });\n };\n\n if (typeof uri === 'string') {\n if (targetFile.type.startsWith('image/')) {\n const image = new Image();\n image.src = uri;\n image.onload = () => {\n returnMediaData({\n uri,\n width: image.naturalWidth ?? image.width,\n height: image.naturalHeight ?? image.height,\n type: 'image',\n mimeType: targetFile.type,\n fileName: targetFile.name,\n fileSize: targetFile.size,\n });\n };\n image.onerror = () => returnRaw();\n } else if (targetFile.type.startsWith('video/')) {\n const video = document.createElement('video');\n video.preload = 'metadata';\n video.src = uri;\n video.onloadedmetadata = () => {\n returnMediaData({\n uri,\n width: video.videoWidth,\n height: video.videoHeight,\n type: 'video',\n mimeType: targetFile.type,\n fileName: targetFile.name,\n fileSize: targetFile.size,\n duration: video.duration,\n });\n };\n video.onerror = () => returnRaw();\n } else {\n returnRaw();\n }\n } else {\n returnRaw();\n }\n };\n\n reader.readAsDataURL(targetFile);\n });\n}\n\nfunction createMediaTypeFormat(mediaTypes: MediaType[]): string {\n const filteredMediaTypes = mediaTypes.filter((mediaType) => mediaType !== 'livePhotos');\n if (filteredMediaTypes.length === 0) {\n return 'image/*';\n }\n let result = '';\n for (const mediaType of filteredMediaTypes) {\n // Make sure the types don't repeat\n if (!result.includes(MediaTypeInput[mediaType])) {\n result = result.concat(',', MediaTypeInput[mediaType]);\n }\n }\n return result;\n}\n"]}
1
+ {"version":3,"file":"ExponentImagePicker.web.js","sourceRoot":"","sources":["../src/ExponentImagePicker.web.ts"],"names":[],"mappings":"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","sourcesContent":["import { PermissionResponse, PermissionStatus, Platform } from 'expo-modules-core';\n\nimport {\n ImagePickerAsset,\n ImagePickerResult,\n MediaType,\n MediaTypeOptions,\n OpenFileBrowserOptions,\n} from './ImagePicker.types';\nimport { parseMediaTypes } from './utils';\n\nconst MediaTypeInput: Record<MediaType, string> = {\n images: 'image/*',\n videos: 'video/mp4,video/quicktime,video/x-m4v,video/*',\n livePhotos: '',\n};\n\nexport default {\n async launchImageLibraryAsync({\n mediaTypes = ['images'] as MediaType[],\n allowsMultipleSelection = false,\n base64 = false,\n }): Promise<ImagePickerResult> {\n // SSR guard\n if (!Platform.isDOMAvailable) {\n return { canceled: true, assets: null };\n }\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n base64,\n });\n },\n\n async launchCameraAsync({\n mediaTypes = MediaTypeOptions.Images,\n allowsMultipleSelection = false,\n base64 = false,\n }): Promise<ImagePickerResult> {\n // SSR guard\n if (!Platform.isDOMAvailable) {\n return { canceled: true, assets: null };\n }\n return await openFileBrowserAsync({\n mediaTypes,\n allowsMultipleSelection,\n capture: true,\n base64,\n });\n },\n\n /*\n * Delegate to expo-permissions to request camera permissions\n */\n async getCameraPermissionsAsync() {\n return permissionGrantedResponse();\n },\n async requestCameraPermissionsAsync() {\n return permissionGrantedResponse();\n },\n\n /*\n * Camera roll permissions don't need to be requested on web, so we always\n * respond with granted.\n */\n async getMediaLibraryPermissionsAsync(_writeOnly: boolean) {\n return permissionGrantedResponse();\n },\n async requestMediaLibraryPermissionsAsync(_writeOnly: boolean): Promise<PermissionResponse> {\n return permissionGrantedResponse();\n },\n};\n\nfunction permissionGrantedResponse(): PermissionResponse {\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n granted: true,\n canAskAgain: true,\n };\n}\n\nfunction openFileBrowserAsync({\n mediaTypes,\n capture = false,\n allowsMultipleSelection = false,\n base64,\n}: OpenFileBrowserOptions): Promise<ImagePickerResult> {\n const parsedMediaTypes = parseMediaTypes(mediaTypes);\n\n const mediaTypeFormat = createMediaTypeFormat(parsedMediaTypes);\n\n const input = document.createElement('input');\n input.style.display = 'none';\n input.setAttribute('type', 'file');\n input.setAttribute('accept', mediaTypeFormat);\n input.setAttribute('id', String(Math.random()));\n input.setAttribute('data-testid', 'file-input');\n if (allowsMultipleSelection) {\n input.setAttribute('multiple', 'multiple');\n }\n if (capture) {\n input.setAttribute('capture', 'camera');\n }\n document.body.appendChild(input);\n\n return new Promise((resolve) => {\n input.addEventListener('change', async () => {\n if (input.files?.length) {\n const files = allowsMultipleSelection ? input.files : [input.files[0]];\n const assets: ImagePickerAsset[] = await Promise.all(\n Array.from(files).map((file) => readFile(file, { base64 }))\n );\n\n resolve({ canceled: false, assets });\n } else {\n resolve({ canceled: true, assets: null });\n }\n document.body.removeChild(input);\n });\n input.addEventListener('cancel', () => {\n input.dispatchEvent(new Event('change'));\n });\n\n const event = new MouseEvent('click');\n input.dispatchEvent(event);\n });\n}\n\nfunction readFile(targetFile: File, options: { base64: boolean }): Promise<ImagePickerAsset> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => {\n reject(new Error(`Failed to read the selected media because the operation failed.`));\n };\n reader.onload = ({ target }) => {\n const uri = (target as any).result;\n const returnRaw = () => resolve({ uri, width: 0, height: 0 });\n const returnMediaData = (data: ImagePickerAsset) => {\n resolve({\n ...data,\n ...(options.base64 && { base64: uri.substr(uri.indexOf(',') + 1) }),\n file: targetFile,\n });\n };\n\n if (typeof uri === 'string') {\n if (targetFile.type.startsWith('image/')) {\n const image = new Image();\n image.src = uri;\n image.onload = () => {\n returnMediaData({\n uri,\n width: image.naturalWidth ?? image.width,\n height: image.naturalHeight ?? image.height,\n type: 'image',\n mimeType: targetFile.type,\n fileName: targetFile.name,\n fileSize: targetFile.size,\n });\n };\n image.onerror = () => returnRaw();\n } else if (targetFile.type.startsWith('video/')) {\n const video = document.createElement('video');\n video.preload = 'metadata';\n video.src = uri;\n video.onloadedmetadata = () => {\n returnMediaData({\n uri,\n width: video.videoWidth,\n height: video.videoHeight,\n type: 'video',\n mimeType: targetFile.type,\n fileName: targetFile.name,\n fileSize: targetFile.size,\n duration: video.duration,\n });\n };\n video.onerror = () => returnRaw();\n } else {\n returnRaw();\n }\n } else {\n returnRaw();\n }\n };\n\n reader.readAsDataURL(targetFile);\n });\n}\n\nfunction createMediaTypeFormat(mediaTypes: MediaType[]): string {\n const filteredMediaTypes = mediaTypes.filter((mediaType) => mediaType !== 'livePhotos');\n if (filteredMediaTypes.length === 0) {\n return 'image/*';\n }\n let result = '';\n for (const mediaType of filteredMediaTypes) {\n // Make sure the types don't repeat\n if (!result.includes(MediaTypeInput[mediaType])) {\n result = result.concat(',', MediaTypeInput[mediaType]);\n }\n }\n return result;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-image-picker",
3
- "version": "16.0.2",
3
+ "version": "16.0.3",
4
4
  "description": "Provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera.",
5
5
  "main": "build/ImagePicker.js",
6
6
  "types": "build/ImagePicker.d.ts",
@@ -39,10 +39,11 @@
39
39
  "expo-image-loader": "~5.0.0"
40
40
  },
41
41
  "devDependencies": {
42
- "expo-module-scripts": "^4.0.0"
42
+ "expo-module-scripts": "^4.0.0",
43
+ "@testing-library/user-event": "^14.5.2"
43
44
  },
44
45
  "peerDependencies": {
45
46
  "expo": "*"
46
47
  },
47
- "gitHead": "b7b95a93855cb4863b626c4524fc6e8b3a2305eb"
48
+ "gitHead": "6cbc7c671f769d36e4294f25a9445281912e45fd"
48
49
  }
@@ -95,6 +95,7 @@ function openFileBrowserAsync({
95
95
  input.setAttribute('type', 'file');
96
96
  input.setAttribute('accept', mediaTypeFormat);
97
97
  input.setAttribute('id', String(Math.random()));
98
+ input.setAttribute('data-testid', 'file-input');
98
99
  if (allowsMultipleSelection) {
99
100
  input.setAttribute('multiple', 'multiple');
100
101
  }
@@ -105,7 +106,7 @@ function openFileBrowserAsync({
105
106
 
106
107
  return new Promise((resolve) => {
107
108
  input.addEventListener('change', async () => {
108
- if (input.files) {
109
+ if (input.files?.length) {
109
110
  const files = allowsMultipleSelection ? input.files : [input.files[0]];
110
111
  const assets: ImagePickerAsset[] = await Promise.all(
111
112
  Array.from(files).map((file) => readFile(file, { base64 }))
@@ -117,6 +118,9 @@ function openFileBrowserAsync({
117
118
  }
118
119
  document.body.removeChild(input);
119
120
  });
121
+ input.addEventListener('cancel', () => {
122
+ input.dispatchEvent(new Event('change'));
123
+ });
120
124
 
121
125
  const event = new MouseEvent('click');
122
126
  input.dispatchEvent(event);