expo-media-library 17.1.0-canary-20250131-5c4e588 → 17.1.0-canary-20250219-4a5dade

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
@@ -14,6 +14,7 @@
14
14
 
15
15
  - [Android] Started using expo modules gradle plugin. ([#34176](https://github.com/expo/expo/pull/34176) by [@lukmccall](https://github.com/lukmccall))
16
16
  - [apple] Migrate remaining `expo-module.config.json` to unified platform syntax. ([#34445](https://github.com/expo/expo/pull/34445) by [@reichhartd](https://github.com/reichhartd))
17
+ - Add guards when using the module in expo go. ([#34738](https://github.com/expo/expo/pull/34738) by [@alanjhughes](https://github.com/alanjhughes))
17
18
 
18
19
  ## 17.0.4 - 2024-12-19
19
20
 
@@ -1,22 +1,6 @@
1
- apply plugin: 'com.android.library'
2
-
3
- def useLegacyExpoModulesCorePlugin = {
4
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
5
- apply from: expoModulesCorePlugin
6
- applyKotlinExpoModulesCorePlugin()
7
- useCoreDependencies()
8
- useDefaultAndroidSdkVersions()
9
- useExpoPublishing()
10
- }
11
-
12
- try {
13
- apply plugin: 'expo-module-gradle-plugin'
14
- } catch (e) {
15
- if (!e instanceof UnknownPluginException) {
16
- throw e
17
- }
18
-
19
- useLegacyExpoModulesCorePlugin()
1
+ plugins {
2
+ id 'com.android.library'
3
+ id 'expo-module-gradle-plugin'
20
4
  }
21
5
 
22
6
  group = 'host.exp.exponent'
@@ -57,6 +57,16 @@ class MediaLibraryModule : Module() {
57
57
  private var imagesObserver: MediaStoreContentObserver? = null
58
58
  private var videosObserver: MediaStoreContentObserver? = null
59
59
  private var awaitingAction: Action? = null
60
+ private val isExpoGo by lazy {
61
+ context.resources.getString(R.string.is_expo_go).toBoolean()
62
+ }
63
+ private val allowedPermissionsList by lazy {
64
+ if (isExpoGo) {
65
+ listOf(GranularPermission.AUDIO)
66
+ } else {
67
+ listOf(GranularPermission.AUDIO, GranularPermission.PHOTO, GranularPermission.VIDEO)
68
+ }
69
+ }
60
70
 
61
71
  override fun definition() = ModuleDefinition {
62
72
  Name("ExpoMediaLibrary")
@@ -72,7 +82,8 @@ class MediaLibraryModule : Module() {
72
82
  Events(LIBRARY_DID_CHANGE_EVENT)
73
83
 
74
84
  AsyncFunction("requestPermissionsAsync") { writeOnly: Boolean, permissions: List<GranularPermission>?, promise: Promise ->
75
- val granularPermissions = permissions ?: listOf(GranularPermission.AUDIO, GranularPermission.PHOTO, GranularPermission.VIDEO)
85
+ val granularPermissions = permissions ?: allowedPermissionsList
86
+ maybeThrowIfExpoGo(granularPermissions)
76
87
  askForPermissionsWithPermissionsManager(
77
88
  appContext.permissions,
78
89
  MediaLibraryPermissionPromiseWrapper(granularPermissions, promise, WeakReference(context)),
@@ -81,7 +92,8 @@ class MediaLibraryModule : Module() {
81
92
  }
82
93
 
83
94
  AsyncFunction("getPermissionsAsync") { writeOnly: Boolean, permissions: List<GranularPermission>?, promise: Promise ->
84
- val granularPermissions = permissions ?: listOf(GranularPermission.AUDIO, GranularPermission.PHOTO, GranularPermission.VIDEO)
95
+ val granularPermissions = permissions ?: allowedPermissionsList
96
+ maybeThrowIfExpoGo(granularPermissions)
85
97
  getPermissionsWithPermissionsManager(
86
98
  appContext.permissions,
87
99
  MediaLibraryPermissionPromiseWrapper(granularPermissions, promise, WeakReference(context)),
@@ -284,14 +296,15 @@ class MediaLibraryModule : Module() {
284
296
  )
285
297
  }
286
298
 
287
- videosObserver = MediaStoreContentObserver(handler, MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
288
- .also { videoObserver ->
289
- contentResolver.registerContentObserver(
290
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
291
- true,
292
- videoObserver
293
- )
294
- }
299
+ videosObserver =
300
+ MediaStoreContentObserver(handler, MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
301
+ .also { videoObserver ->
302
+ contentResolver.registerContentObserver(
303
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
304
+ true,
305
+ videoObserver
306
+ )
307
+ }
295
308
  }
296
309
 
297
310
  OnStopObserving {
@@ -322,15 +335,16 @@ class MediaLibraryModule : Module() {
322
335
  }
323
336
  }
324
337
 
325
- private inline fun withModuleScope(promise: Promise, crossinline block: () -> Unit) = moduleCoroutineScope.launch {
326
- try {
327
- block()
328
- } catch (e: CodedException) {
329
- promise.reject(e)
330
- } catch (e: ModuleDestroyedException) {
331
- promise.reject(TAG, "MediaLibrary module destroyed", e)
338
+ private inline fun withModuleScope(promise: Promise, crossinline block: () -> Unit) =
339
+ moduleCoroutineScope.launch {
340
+ try {
341
+ block()
342
+ } catch (e: CodedException) {
343
+ promise.reject(e)
344
+ } catch (e: ModuleDestroyedException) {
345
+ promise.reject(TAG, "MediaLibrary module destroyed", e)
346
+ }
332
347
  }
333
- }
334
348
 
335
349
  private val isMissingPermissions: Boolean
336
350
  get() = hasReadPermissions()
@@ -339,7 +353,10 @@ class MediaLibraryModule : Module() {
339
353
  get() = hasWritePermissions()
340
354
 
341
355
  @SuppressLint("InlinedApi")
342
- private fun getManifestPermissions(writeOnly: Boolean, granularPermissions: List<GranularPermission>): Array<String> {
356
+ private fun getManifestPermissions(
357
+ writeOnly: Boolean,
358
+ granularPermissions: List<GranularPermission>
359
+ ): Array<String> {
343
360
  // ACCESS_MEDIA_LOCATION should not be requested if it's absent in android-manifest
344
361
  // If only audio permission is requested, we don't need to request media location permissions
345
362
  val shouldAddMediaLocationAccess =
@@ -347,7 +364,9 @@ class MediaLibraryModule : Module() {
347
364
  MediaLibraryUtils.hasManifestPermission(context, ACCESS_MEDIA_LOCATION) &&
348
365
  !(
349
366
  Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
350
- granularPermissions.count() == 1 && granularPermissions.contains(GranularPermission.AUDIO)
367
+ granularPermissions.count() == 1 && granularPermissions.contains(
368
+ GranularPermission.AUDIO
369
+ )
351
370
  )
352
371
 
353
372
  val shouldAddWriteExternalStorage =
@@ -356,7 +375,12 @@ class MediaLibraryModule : Module() {
356
375
 
357
376
  val shouldAddGranularPermissions =
358
377
  Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
359
- granularPermissions.all { MediaLibraryUtils.hasManifestPermission(context, it.toManifestPermission()) }
378
+ granularPermissions.all {
379
+ MediaLibraryUtils.hasManifestPermission(
380
+ context,
381
+ it.toManifestPermission()
382
+ )
383
+ }
360
384
 
361
385
  val shouldIncludeGranular = shouldAddGranularPermissions && !writeOnly
362
386
  return listOfNotNull(
@@ -368,7 +392,10 @@ class MediaLibraryModule : Module() {
368
392
  }
369
393
 
370
394
  @SuppressLint("InlinedApi")
371
- private fun getGranularPermissions(shouldIncludeGranular: Boolean, granularPermissions: List<GranularPermission>): Array<String> {
395
+ private fun getGranularPermissions(
396
+ shouldIncludeGranular: Boolean,
397
+ granularPermissions: List<GranularPermission>
398
+ ): Array<String> {
372
399
  return if (shouldIncludeGranular) {
373
400
  listOfNotNull(
374
401
  READ_MEDIA_IMAGES.takeIf { granularPermissions.contains(GranularPermission.PHOTO) },
@@ -381,9 +408,11 @@ class MediaLibraryModule : Module() {
381
408
  }
382
409
 
383
410
  private inline fun throwUnlessPermissionsGranted(isWrite: Boolean = true, block: () -> Unit) {
384
- val missingPermissionsCondition = if (isWrite) isMissingWritePermission else isMissingPermissions
411
+ val missingPermissionsCondition =
412
+ if (isWrite) isMissingWritePermission else isMissingPermissions
385
413
  if (missingPermissionsCondition) {
386
- val missingPermissionsMessage = if (isWrite) ERROR_NO_WRITE_PERMISSION_MESSAGE else ERROR_NO_PERMISSIONS_MESSAGE
414
+ val missingPermissionsMessage =
415
+ if (isWrite) ERROR_NO_WRITE_PERMISSION_MESSAGE else ERROR_NO_PERMISSIONS_MESSAGE
387
416
  throw PermissionsException(missingPermissionsMessage)
388
417
  }
389
418
  block()
@@ -395,7 +424,7 @@ class MediaLibraryModule : Module() {
395
424
 
396
425
  private fun hasReadPermissions(): Boolean {
397
426
  return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
398
- val permissions = mutableListOf(READ_MEDIA_IMAGES, READ_MEDIA_AUDIO, READ_MEDIA_VIDEO)
427
+ val permissions = allowedPermissionsList.map { it.toManifestPermission() }.toMutableList()
399
428
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
400
429
  permissions.add(READ_MEDIA_VISUAL_USER_SELECTED)
401
430
  }
@@ -413,6 +442,14 @@ class MediaLibraryModule : Module() {
413
442
  }
414
443
  }
415
444
 
445
+ private fun maybeThrowIfExpoGo(permissions: List<GranularPermission>) {
446
+ if (isExpoGo) {
447
+ if (permissions.contains(GranularPermission.PHOTO) || permissions.contains(GranularPermission.VIDEO)) {
448
+ throw PermissionsException("Due to changes in Androids permission requirements, Expo Go can no longer provide full access to the media library. To test the full functionality of this module, you can create a development build")
449
+ }
450
+ }
451
+ }
452
+
416
453
  private fun hasWritePermissions() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
417
454
  false
418
455
  } else {
@@ -0,0 +1,3 @@
1
+ <resources>
2
+ <string name="is_expo_go">false</string>
3
+ </resources>
@@ -1 +1 @@
1
- {"version":3,"file":"MediaLibrary.d.ts","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MediaLibrary.d.ts","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,12 @@
1
1
  import { PermissionStatus, createPermissionHook, UnavailabilityError, } from 'expo-modules-core';
2
2
  import { Platform } from 'react-native';
3
3
  import MediaLibrary from './ExpoMediaLibrary';
4
+ const isExpoGo = typeof expo !== 'undefined' && globalThis.expo?.modules?.ExpoGo;
5
+ let loggedExpoGoWarning = false;
6
+ if (isExpoGo && !loggedExpoGoWarning) {
7
+ console.warn('Due to changes in Androids permission requirements, Expo Go can no longer provide full access to the media library. To test the full functionality of this module, you can create a development build. https://docs.expo.dev/develop/development-builds/create-a-build');
8
+ loggedExpoGoWarning = true;
9
+ }
4
10
  export { PermissionStatus, };
5
11
  function arrayize(item) {
6
12
  if (Array.isArray(item)) {
@@ -81,7 +87,7 @@ export async function isAvailableAsync() {
81
87
  * effect only on Android 13 and newer. By default, `expo-media-library` will ask for all possible permissions.
82
88
  * @return A promise that fulfils with [`PermissionResponse`](#permissionresponse) object.
83
89
  */
84
- export async function requestPermissionsAsync(writeOnly = false, granularPermissions = ['audio', 'photo', 'video']) {
90
+ export async function requestPermissionsAsync(writeOnly = false, granularPermissions) {
85
91
  if (!MediaLibrary.requestPermissionsAsync) {
86
92
  throw new UnavailabilityError('MediaLibrary', 'requestPermissionsAsync');
87
93
  }
@@ -98,7 +104,7 @@ export async function requestPermissionsAsync(writeOnly = false, granularPermiss
98
104
  * an effect only on Android 13 and newer. By default, `expo-media-library` will ask for all possible permissions.
99
105
  * @return A promise that fulfils with [`PermissionResponse`](#permissionresponse) object.
100
106
  */
101
- export async function getPermissionsAsync(writeOnly = false, granularPermissions = ['audio', 'photo', 'video']) {
107
+ export async function getPermissionsAsync(writeOnly = false, granularPermissions) {
102
108
  if (!MediaLibrary.getPermissionsAsync) {
103
109
  throw new UnavailabilityError('MediaLibrary', 'getPermissionsAsync');
104
110
  }
@@ -138,6 +144,9 @@ export const usePermissions = createPermissionHook({
138
144
  * @platform ios
139
145
  */
140
146
  export async function presentPermissionsPickerAsync(mediaTypes = ['photo', 'video']) {
147
+ if (Platform.OS === 'android' && isExpoGo) {
148
+ throw new UnavailabilityError('MediaLibrary', 'presentPermissionsPickerAsync is unavailable in Expo Go');
149
+ }
141
150
  if (Platform.OS === 'android' && Platform.Version >= 34) {
142
151
  await MediaLibrary.requestPermissionsAsync(false, mediaTypes);
143
152
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"MediaLibrary.js","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n PermissionResponse as EXPermissionResponse,\n PermissionStatus,\n PermissionExpiration,\n PermissionHookOptions,\n createPermissionHook,\n UnavailabilityError,\n EventSubscription,\n} from 'expo-modules-core';\nimport { Platform } from 'react-native';\n\nimport MediaLibrary from './ExpoMediaLibrary';\n\n// @needsAudit\nexport type PermissionResponse = EXPermissionResponse & {\n /**\n * Indicates if your app has access to the whole or only part of the photo library. Possible values are:\n * - `'all'` if the user granted your app access to the whole photo library\n * - `'limited'` if the user granted your app access only to selected photos (only available on Android API 14+ and iOS 14.0+)\n * - `'none'` if user denied or hasn't yet granted the permission\n */\n accessPrivileges?: 'all' | 'limited' | 'none';\n};\n\n/**\n * Determines the type of media that the app will ask the OS to get access to.\n * @platform android 13+\n */\nexport type GranularPermission = 'audio' | 'photo' | 'video';\n\nexport type MediaTypeValue = 'audio' | 'photo' | 'video' | 'unknown' | 'pairedVideo';\n\n/**\n * Represents the possible types of media that the app will ask the OS to get access to when calling [`presentPermissionsPickerAsync()`](#medialibrarypresentpermissionspickerasyncmediatypes).\n * @platform android 14+\n * */\nexport type MediaTypeFilter = 'photo' | 'video';\n\nexport type SortByKey =\n | 'default'\n | 'mediaType'\n | 'width'\n | 'height'\n | 'creationTime'\n | 'modificationTime'\n | 'duration';\nexport type SortByValue = [SortByKey, boolean] | SortByKey;\n\nexport type MediaTypeObject = {\n audio: 'audio';\n photo: 'photo';\n video: 'video';\n unknown: 'unknown';\n};\n\nexport type SortByObject = {\n default: 'default';\n mediaType: 'mediaType';\n width: 'width';\n height: 'height';\n creationTime: 'creationTime';\n modificationTime: 'modificationTime';\n duration: 'duration';\n};\n\n// @needsAudit\nexport type Asset = {\n /**\n * Internal ID that represents an asset.\n */\n id: string;\n /**\n * Filename of the asset.\n */\n filename: string;\n /**\n * URI that points to the asset. `ph://*` (iOS), `file://*` (Android)\n */\n uri: string;\n /**\n * Media type.\n */\n mediaType: MediaTypeValue;\n /**\n * An array of media subtypes.\n * @platform ios\n */\n mediaSubtypes?: MediaSubtype[];\n /**\n * Width of the image or video.\n */\n width: number;\n /**\n * Height of the image or video.\n */\n height: number;\n /**\n * File creation timestamp.\n */\n creationTime: number;\n /**\n * Last modification timestamp.\n */\n modificationTime: number;\n /**\n * Duration of the video or audio asset in seconds.\n */\n duration: number;\n /**\n * Album ID that the asset belongs to.\n * @platform android\n */\n albumId?: string;\n};\n\n// @needsAudit\nexport type AssetInfo = Asset & {\n /**\n * Local URI for the asset.\n */\n localUri?: string;\n /**\n * GPS location if available.\n */\n location?: Location;\n /**\n * EXIF metadata associated with the image.\n */\n exif?: object;\n /**\n * Whether the asset is marked as favorite.\n * @platform ios\n */\n isFavorite?: boolean;\n /**\n * This field is available only if flag `shouldDownloadFromNetwork` is set to `false`.\n * Whether the asset is stored on the network (iCloud on iOS).\n * @platform ios\n */\n isNetworkAsset?: boolean; //iOS only\n /**\n * Display orientation of the image. Orientation is available only for assets whose\n * `mediaType` is `MediaType.photo`. Value will range from 1 to 8, see [EXIF orientation specification](http://sylvana.net/jpegcrop/exif_orientation.html)\n * for more details.\n * @platform ios\n */\n orientation?: number;\n /**\n * Contains information about the video paired with the image file.\n * This field is available if the `mediaType` is `\"photo\"`, and the `mediaSubtypes` includes `\"livePhoto\"`.\n * @platform ios\n */\n pairedVideoAsset?: Asset | null;\n};\n\n/**\n * Constants identifying specific variations of asset media, such as panorama or screenshot photos,\n * and time-lapse or high-frame-rate video. Maps to [these values](https://developer.apple.com/documentation/photokit/phassetmediasubtype#1603888).\n * */\nexport type MediaSubtype =\n | 'depthEffect'\n | 'hdr'\n | 'highFrameRate'\n | 'livePhoto'\n | 'panorama'\n | 'screenshot'\n | 'stream'\n | 'timelapse';\n\n// @needsAudit\nexport type MediaLibraryAssetInfoQueryOptions = {\n /**\n * Whether allow the asset to be downloaded from network. Only available in iOS with iCloud assets.\n * @default true\n */\n shouldDownloadFromNetwork?: boolean;\n};\n\n// @needsAudit\nexport type MediaLibraryAssetsChangeEvent = {\n /**\n * Whether the media library's changes could be described as \"incremental changes\".\n * `true` indicates the changes are described by the `insertedAssets`, `deletedAssets` and\n * `updatedAssets` values. `false` indicates that the scope of changes is too large and you\n * should perform a full assets reload (eg. a user has changed access to individual assets in the\n * media library).\n */\n hasIncrementalChanges: boolean;\n /**\n * Available only if `hasIncrementalChanges` is `true`.\n * Array of [`Asset`](#asset)s that have been inserted to the library.\n */\n insertedAssets?: Asset[];\n /**\n * Available only if `hasIncrementalChanges` is `true`.\n * Array of [`Asset`](#asset)s that have been deleted from the library.\n */\n deletedAssets?: Asset[];\n /**\n * Available only if `hasIncrementalChanges` is `true`.\n * Array of [`Asset`](#asset)s that have been updated or completed downloading from network\n * storage (iCloud on iOS).\n */\n updatedAssets?: Asset[];\n};\n\n// @docsMissing\nexport type Location = {\n latitude: number;\n longitude: number;\n};\n\n// @needsAudit\nexport type Album = {\n /**\n * Album ID.\n */\n id: string;\n /**\n * Album title.\n */\n title: string;\n /**\n * Estimated number of assets in the album.\n */\n assetCount: number;\n /**\n * The type of the assets album.\n * @platform ios\n */\n type?: AlbumType;\n /**\n * Apply only to albums whose type is `'moment'`. Earliest creation timestamp of all\n * assets in the moment.\n * @platform ios\n */\n startTime: number;\n /**\n * Apply only to albums whose type is `'moment'`. Latest creation timestamp of all\n * assets in the moment.\n * @platform ios\n */\n endTime: number;\n /**\n * Apply only to albums whose type is `'moment'`. Approximated location of all\n * assets in the moment.\n * @platform ios\n */\n approximateLocation?: Location;\n /**\n * Apply only to albums whose type is `'moment'`. Names of locations grouped\n * in the moment.\n * @platform ios\n */\n locationNames?: string[];\n};\n\n// @docsMissing\nexport type AlbumType = 'album' | 'moment' | 'smartAlbum';\n\n// @docsMissing\nexport type AlbumsOptions = {\n includeSmartAlbums?: boolean;\n};\n\n// @needsAudit\nexport type AssetsOptions = {\n /**\n * The maximum number of items on a single page.\n * @default 20\n */\n first?: number;\n /**\n * Asset ID of the last item returned on the previous page. To get the ID of the next page,\n * pass [`endCursor`](#pagedinfo) as its value.\n */\n after?: AssetRef;\n /**\n * [Album](#album) or its ID to get assets from specific album.\n */\n album?: AlbumRef;\n /**\n * An array of [`SortByValue`](#sortbyvalue)s or a single `SortByValue` value. By default, all\n * keys are sorted in descending order, however you can also pass a pair `[key, ascending]` where\n * the second item is a `boolean` value that means whether to use ascending order. Note that if\n * the `SortBy.default` key is used, then `ascending` argument will not matter. Earlier items have\n * higher priority when sorting out the results.\n * If empty, this method uses the default sorting that is provided by the platform.\n */\n sortBy?: SortByValue[] | SortByValue;\n /**\n * An array of [MediaTypeValue](#mediatypevalue)s or a single `MediaTypeValue`.\n * @default MediaType.photo\n */\n mediaType?: MediaTypeValue[] | MediaTypeValue;\n /**\n * `Date` object or Unix timestamp in milliseconds limiting returned assets only to those that\n * were created after this date.\n */\n createdAfter?: Date | number;\n /**\n * Similarly as `createdAfter`, but limits assets only to those that were created before specified\n * date.\n */\n createdBefore?: Date | number;\n};\n\n// @needsAudit\nexport type PagedInfo<T> = {\n /**\n * A page of [`Asset`](#asset)s fetched by the query.\n */\n assets: T[];\n /**\n * ID of the last fetched asset. It should be passed as `after` option in order to get the\n * next page.\n */\n endCursor: string;\n /**\n * Whether there are more assets to fetch.\n */\n hasNextPage: boolean;\n /**\n * Estimated total number of assets that match the query.\n */\n totalCount: number;\n};\n\n// @docsMissing\nexport type AssetRef = Asset | string;\n\n// @docsMissing\nexport type AlbumRef = Album | string;\n\nexport {\n PermissionStatus,\n PermissionExpiration,\n EXPermissionResponse,\n PermissionHookOptions,\n EventSubscription as Subscription,\n};\n\nfunction arrayize(item: any): any[] {\n if (Array.isArray(item)) {\n return item;\n }\n return item ? [item] : [];\n}\n\nfunction getId(ref: any): string | undefined {\n if (typeof ref === 'string') {\n return ref;\n }\n return ref ? ref.id : undefined;\n}\n\nfunction checkAssetIds(assetIds: any): void {\n if (assetIds.some((id) => !id || typeof id !== 'string')) {\n throw new Error('Asset ID must be a string!');\n }\n}\n\nfunction checkAlbumIds(albumIds: any): void {\n if (albumIds.some((id) => !id || typeof id !== 'string')) {\n throw new Error('Album ID must be a string!');\n }\n}\n\nfunction checkMediaType(mediaType: any): void {\n if (Object.values(MediaType).indexOf(mediaType) === -1) {\n throw new Error(`Invalid mediaType: ${mediaType}`);\n }\n}\n\nfunction checkSortBy(sortBy: any): void {\n if (Array.isArray(sortBy)) {\n checkSortByKey(sortBy[0]);\n\n if (typeof sortBy[1] !== 'boolean') {\n throw new Error('Invalid sortBy array argument. Second item must be a boolean!');\n }\n } else {\n checkSortByKey(sortBy);\n }\n}\n\nfunction checkSortByKey(sortBy: any): void {\n if (Object.values(SortBy).indexOf(sortBy) === -1) {\n throw new Error(`Invalid sortBy key: ${sortBy}`);\n }\n}\n\nfunction sortByOptionToString(sortBy: any) {\n if (Array.isArray(sortBy)) {\n return `${sortBy[0]} ${sortBy[1] ? 'ASC' : 'DESC'}`;\n }\n return `${sortBy} DESC`;\n}\n\nfunction dateToNumber(value?: Date | number): number | undefined {\n return value instanceof Date ? value.getTime() : value;\n}\n\n// @needsAudit\n/**\n * Possible media types.\n */\nexport const MediaType: MediaTypeObject = MediaLibrary.MediaType;\n\n// @needsAudit\n/**\n * Supported keys that can be used to sort `getAssetsAsync` results.\n */\nexport const SortBy: SortByObject = MediaLibrary.SortBy;\n\n// @needsAudit\n/**\n * Returns whether the Media Library API is enabled on the current device.\n * @return A promise which fulfils with a `boolean`, indicating whether the Media Library API is\n * available on the current device.\n */\nexport async function isAvailableAsync(): Promise<boolean> {\n return !!MediaLibrary && 'getAssetsAsync' in MediaLibrary;\n}\n\n// @needsAudit @docsMissing\n/**\n * Asks the user to grant permissions for accessing media in user's media library.\n * @param writeOnly\n * @param granularPermissions - A list of [`GranularPermission`](#granularpermission) values. This parameter has an\n * effect only on Android 13 and newer. By default, `expo-media-library` will ask for all possible permissions.\n * @return A promise that fulfils with [`PermissionResponse`](#permissionresponse) object.\n */\nexport async function requestPermissionsAsync(\n writeOnly: boolean = false,\n granularPermissions: GranularPermission[] = ['audio', 'photo', 'video']\n): Promise<PermissionResponse> {\n if (!MediaLibrary.requestPermissionsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'requestPermissionsAsync');\n }\n if (Platform.OS === 'android') {\n return await MediaLibrary.requestPermissionsAsync(writeOnly, granularPermissions);\n }\n return await MediaLibrary.requestPermissionsAsync(writeOnly);\n}\n\n// @needsAudit @docsMissing\n/**\n * Checks user's permissions for accessing media library.\n * @param writeOnly\n * @param granularPermissions - A list of [`GranularPermission`](#granularpermission) values. This parameter has\n * an effect only on Android 13 and newer. By default, `expo-media-library` will ask for all possible permissions.\n * @return A promise that fulfils with [`PermissionResponse`](#permissionresponse) object.\n */\nexport async function getPermissionsAsync(\n writeOnly: boolean = false,\n granularPermissions: GranularPermission[] = ['audio', 'photo', 'video']\n): Promise<PermissionResponse> {\n if (!MediaLibrary.getPermissionsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getPermissionsAsync');\n }\n if (Platform.OS === 'android') {\n return await MediaLibrary.getPermissionsAsync(writeOnly, granularPermissions);\n }\n return await MediaLibrary.getPermissionsAsync(writeOnly);\n}\n\n// @needsAudit\n/**\n * Check or request permissions to access the media library.\n * This uses both `requestPermissionsAsync` and `getPermissionsAsync` to interact with the permissions.\n *\n * @example\n * ```ts\n * const [permissionResponse, requestPermission] = MediaLibrary.usePermissions();\n * ```\n */\nexport const usePermissions = createPermissionHook<\n PermissionResponse,\n { writeOnly?: boolean; granularPermissions?: GranularPermission[] }\n>({\n // TODO(cedric): permission requesters should have an options param or a different requester\n getMethod: (options) => getPermissionsAsync(options?.writeOnly, options?.granularPermissions),\n requestMethod: (options) =>\n requestPermissionsAsync(options?.writeOnly, options?.granularPermissions),\n});\n\n// @needsAudit\n/**\n * Allows the user to update the assets that your app has access to.\n * The system modal is only displayed if the user originally allowed only `limited` access to their\n * media library, otherwise this method is a no-op.\n * @param mediaTypes Limits the type(s) of media that the user will be granting access to. By default, a list that shows both photos and videos is presented.\n *\n * @return A promise that either rejects if the method is unavailable, or resolves to `void`.\n * > __Note:__ This method doesn't inform you if the user changes which assets your app has access to.\n * That information is only exposed by iOS, and to obtain it, you need to subscribe for updates to the user's media library using [`addListener()`](#medialibraryaddlistenerlistener).\n * If `hasIncrementalChanges` is `false`, the user changed their permissions.\n *\n * @platform android 14+\n * @platform ios\n */\nexport async function presentPermissionsPickerAsync(\n mediaTypes: MediaTypeFilter[] = ['photo', 'video']\n): Promise<void> {\n if (Platform.OS === 'android' && Platform.Version >= 34) {\n await MediaLibrary.requestPermissionsAsync(false, mediaTypes);\n return;\n }\n if (!MediaLibrary.presentPermissionsPickerAsync) {\n throw new UnavailabilityError('MediaLibrary', 'presentPermissionsPickerAsync');\n }\n return await MediaLibrary.presentPermissionsPickerAsync();\n}\n\n// @needsAudit\n/**\n * Creates an asset from existing file. The most common use case is to save a picture taken by [Camera](./camera).\n * This method requires `CAMERA_ROLL` permission.\n *\n * @example\n * ```js\n * const { uri } = await Camera.takePictureAsync();\n * const asset = await MediaLibrary.createAssetAsync(uri);\n * ```\n * @param localUri A URI to the image or video file. It must contain an extension. On Android it\n * must be a local path, so it must start with `file:///`\n * @return A promise which fulfils with an object representing an [`Asset`](#asset).\n */\nexport async function createAssetAsync(localUri: string): Promise<Asset> {\n if (!MediaLibrary.createAssetAsync) {\n throw new UnavailabilityError('MediaLibrary', 'createAssetAsync');\n }\n\n if (!localUri || typeof localUri !== 'string') {\n throw new Error('Invalid argument \"localUri\". It must be a string!');\n }\n const asset = await MediaLibrary.createAssetAsync(localUri);\n\n if (Array.isArray(asset)) {\n // Android returns an array with asset, we need to pick the first item\n return asset[0];\n }\n return asset;\n}\n\n// @needsAudit\n/**\n * Saves the file at given `localUri` to the user's media library. Unlike [`createAssetAsync()`](#medialibrarycreateassetasynclocaluri),\n * This method doesn't return created asset.\n * On __iOS 11+__, it's possible to use this method without asking for `CAMERA_ROLL` permission,\n * however then yours `Info.plist` should have `NSPhotoLibraryAddUsageDescription` key.\n * @param localUri A URI to the image or video file. It must contain an extension. On Android it\n * must be a local path, so it must start with `file:///`.\n */\nexport async function saveToLibraryAsync(localUri: string): Promise<void> {\n if (!MediaLibrary.saveToLibraryAsync) {\n throw new UnavailabilityError('MediaLibrary', 'saveToLibraryAsync');\n }\n return await MediaLibrary.saveToLibraryAsync(localUri);\n}\n\n// @needsAudit\n/**\n * Adds array of assets to the album.\n *\n * On Android, by default it copies assets from the current album to provided one, however it's also\n * possible to move them by passing `false` as `copyAssets` argument. In case they're copied you\n * should keep in mind that `getAssetsAsync` will return duplicated assets.\n * @param assets An array of [Asset](#asset) or their IDs.\n * @param album An [Album](#album) or its ID.\n * @param copy __Android only.__ Whether to copy assets to the new album instead of move them.\n * Defaults to `true`.\n * @return Returns promise which fulfils with `true` if the assets were successfully added to\n * the album.\n */\nexport async function addAssetsToAlbumAsync(\n assets: AssetRef[] | AssetRef,\n album: AlbumRef,\n copy: boolean = true\n): Promise<boolean> {\n if (!MediaLibrary.addAssetsToAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'addAssetsToAlbumAsync');\n }\n\n const assetIds = arrayize(assets).map(getId);\n const albumId = getId(album);\n\n checkAssetIds(assetIds);\n\n if (!albumId || typeof albumId !== 'string') {\n throw new Error('Invalid album ID. It must be a string!');\n }\n\n if (Platform.OS === 'ios') {\n return await MediaLibrary.addAssetsToAlbumAsync(assetIds, albumId);\n }\n return await MediaLibrary.addAssetsToAlbumAsync(assetIds, albumId, !!copy);\n}\n\n// @needsAudit\n/**\n * Removes given assets from album.\n *\n * On Android, album will be automatically deleted if there are no more assets inside.\n * @param assets An array of [Asset](#asset) or their IDs.\n * @param album An [Album](#album) or its ID.\n * @return Returns promise which fulfils with `true` if the assets were successfully removed from\n * the album.\n */\nexport async function removeAssetsFromAlbumAsync(\n assets: AssetRef[] | AssetRef,\n album: AlbumRef\n): Promise<boolean> {\n if (!MediaLibrary.removeAssetsFromAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'removeAssetsFromAlbumAsync');\n }\n\n const assetIds = arrayize(assets).map(getId);\n const albumId = getId(album);\n\n checkAssetIds(assetIds);\n return await MediaLibrary.removeAssetsFromAlbumAsync(assetIds, albumId);\n}\n\n// @needsAudit\n/**\n * Deletes assets from the library. On iOS it deletes assets from all albums they belong to, while\n * on Android it keeps all copies of them (album is strictly connected to the asset). Also, there is\n * additional dialog on iOS that requires user to confirm this action.\n * @param assets An array of [Asset](#asset) or their IDs.\n * @return Returns promise which fulfils with `true` if the assets were successfully deleted.\n */\nexport async function deleteAssetsAsync(assets: AssetRef[] | AssetRef): Promise<boolean> {\n if (!MediaLibrary.deleteAssetsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'deleteAssetsAsync');\n }\n\n const assetIds = arrayize(assets).map(getId);\n\n checkAssetIds(assetIds);\n return await MediaLibrary.deleteAssetsAsync(assetIds);\n}\n\n// @needsAudit\n/**\n * Provides more information about an asset, including GPS location, local URI and EXIF metadata.\n * @param asset An [Asset](#asset) or its ID.\n * @param options\n * @return An [AssetInfo](#assetinfo) object, which is an `Asset` extended by an additional fields.\n */\nexport async function getAssetInfoAsync(\n asset: AssetRef,\n options: MediaLibraryAssetInfoQueryOptions = { shouldDownloadFromNetwork: true }\n): Promise<AssetInfo> {\n if (!MediaLibrary.getAssetInfoAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAssetInfoAsync');\n }\n\n const assetId = getId(asset);\n\n checkAssetIds([assetId]);\n\n const assetInfo = await MediaLibrary.getAssetInfoAsync(assetId, options);\n\n if (Array.isArray(assetInfo)) {\n // Android returns an array with asset info, we need to pick the first item\n return assetInfo[0];\n }\n return assetInfo;\n}\n\n// @needsAudit\n/**\n * Queries for user-created albums in media gallery.\n * @return A promise which fulfils with an array of [`Album`](#asset)s. Depending on Android version,\n * root directory of your storage may be listed as album titled `\"0\"` or unlisted at all.\n */\nexport async function getAlbumsAsync({ includeSmartAlbums = false }: AlbumsOptions = {}): Promise<\n Album[]\n> {\n if (!MediaLibrary.getAlbumsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAlbumsAsync');\n }\n return await MediaLibrary.getAlbumsAsync({ includeSmartAlbums });\n}\n\n// @needsAudit\n/**\n * Queries for an album with a specific name.\n * @param title Name of the album to look for.\n * @return An object representing an [`Album`](#album), if album with given name exists, otherwise\n * returns `null`.\n */\nexport async function getAlbumAsync(title: string): Promise<Album> {\n if (!MediaLibrary.getAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAlbumAsync');\n }\n if (typeof title !== 'string') {\n throw new Error('Album title must be a string!');\n }\n return await MediaLibrary.getAlbumAsync(title);\n}\n\n// @needsAudit\n/**\n * Creates an album with given name and initial asset. The asset parameter is required on Android,\n * since it's not possible to create empty album on this platform. On Android, by default it copies\n * given asset from the current album to the new one, however it's also possible to move it by\n * passing `false` as `copyAsset` argument.\n * In case it's copied you should keep in mind that `getAssetsAsync` will return duplicated asset.\n * @param albumName Name of the album to create.\n * @param asset An [Asset](#asset) or its ID (required on Android).\n * @param copyAsset __Android Only.__ Whether to copy asset to the new album instead of move it.\n * Defaults to `true`.\n * @return Newly created [`Album`](#album).\n */\nexport async function createAlbumAsync(\n albumName: string,\n asset?: AssetRef,\n copyAsset: boolean = true\n): Promise<Album> {\n if (!MediaLibrary.createAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'createAlbumAsync');\n }\n\n const assetId = getId(asset);\n\n if (Platform.OS === 'android' && (typeof assetId !== 'string' || assetId.length === 0)) {\n // it's not possible to create empty album on Android, so initial asset must be provided\n throw new Error('MediaLibrary.createAlbumAsync must be called with an asset on Android.');\n }\n if (!albumName || typeof albumName !== 'string') {\n throw new Error('Invalid argument \"albumName\". It must be a string!');\n }\n if (assetId != null && typeof assetId !== 'string') {\n throw new Error('Asset ID must be a string!');\n }\n\n if (Platform.OS === 'ios') {\n return await MediaLibrary.createAlbumAsync(albumName, assetId);\n }\n return await MediaLibrary.createAlbumAsync(albumName, assetId, !!copyAsset);\n}\n\n// @needsAudit\n/**\n * Deletes given albums from the library. On Android by default it deletes assets belonging to given\n * albums from the library. On iOS it doesn't delete these assets, however it's possible to do by\n * passing `true` as `deleteAssets`.\n * @param albums An array of [`Album`](#asset)s or their IDs.\n * @param assetRemove __iOS Only.__ Whether to also delete assets belonging to given albums.\n * Defaults to `false`.\n * @return Returns a promise which fulfils with `true` if the albums were successfully deleted from\n * the library.\n */\nexport async function deleteAlbumsAsync(\n albums: AlbumRef[] | AlbumRef,\n assetRemove: boolean = false\n): Promise<boolean> {\n if (!MediaLibrary.deleteAlbumsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'deleteAlbumsAsync');\n }\n\n const albumIds = arrayize(albums).map(getId);\n\n checkAlbumIds(albumIds);\n if (Platform.OS === 'android') {\n return await MediaLibrary.deleteAlbumsAsync(albumIds);\n }\n return await MediaLibrary.deleteAlbumsAsync(albumIds, !!assetRemove);\n}\n\n// @needsAudit\n/**\n * Fetches a page of assets matching the provided criteria.\n * @param assetsOptions\n * @return A promise that fulfils with to [`PagedInfo`](#pagedinfo) object with array of [`Asset`](#asset)s.\n */\nexport async function getAssetsAsync(assetsOptions: AssetsOptions = {}): Promise<PagedInfo<Asset>> {\n if (!MediaLibrary.getAssetsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAssetsAsync');\n }\n\n const { first, after, album, sortBy, mediaType, createdAfter, createdBefore } = assetsOptions;\n\n const options = {\n first: first == null ? 20 : first,\n after: getId(after),\n album: getId(album),\n sortBy: arrayize(sortBy),\n mediaType: arrayize(mediaType || [MediaType.photo]),\n createdAfter: dateToNumber(createdAfter),\n createdBefore: dateToNumber(createdBefore),\n };\n\n if (first != null && typeof options.first !== 'number') {\n throw new Error('Option \"first\" must be a number!');\n }\n if (after != null && typeof options.after !== 'string') {\n throw new Error('Option \"after\" must be a string!');\n }\n if (album != null && typeof options.album !== 'string') {\n throw new Error('Option \"album\" must be a string!');\n }\n\n if (after != null && Platform.OS === 'android' && isNaN(parseInt(getId(after) as string, 10))) {\n throw new Error('Option \"after\" must be a valid ID!');\n }\n\n if (first != null && first < 0) {\n throw new Error('Option \"first\" must be a positive integer!');\n }\n\n options.sortBy.forEach(checkSortBy);\n options.mediaType.forEach(checkMediaType);\n options.sortBy = options.sortBy.map(sortByOptionToString);\n\n return await MediaLibrary.getAssetsAsync(options);\n}\n\n// @needsAudit\n/**\n * Subscribes for updates in user's media library.\n * @param listener A callback that is fired when any assets have been inserted or deleted from the\n * library. On Android it's invoked with an empty object. On iOS, it's invoked with [`MediaLibraryAssetsChangeEvent`](#medialibraryassetschangeevent)\n * object.\n *\n * Additionally, only on iOS, the listener is also invoked when the user changes access to individual assets in the media library\n * using `presentPermissionsPickerAsync()`.\n * @return An [`Subscription`](#subscription) object that you can call `remove()` on when you would\n * like to unsubscribe the listener.\n */\nexport function addListener(\n listener: (event: MediaLibraryAssetsChangeEvent) => void\n): EventSubscription {\n return MediaLibrary.addListener(MediaLibrary.CHANGE_LISTENER_NAME, listener);\n}\n\n// @docsMissing\nexport function removeSubscription(subscription: EventSubscription): void {\n subscription.remove();\n}\n\n// @needsAudit\n/**\n * Removes all listeners.\n */\nexport function removeAllListeners(): void {\n MediaLibrary.removeAllListeners(MediaLibrary.CHANGE_LISTENER_NAME);\n}\n\n// @needsAudit\n/**\n * Fetches a list of moments, which is a group of assets taken around the same place\n * and time.\n * @return An array of [albums](#album) whose type is `moment`.\n * @platform ios\n */\nexport async function getMomentsAsync() {\n if (!MediaLibrary.getMomentsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getMomentsAsync');\n }\n\n return await MediaLibrary.getMomentsAsync();\n}\n\n// @needsAudit\n/**\n * Moves album content to the special media directories on **Android R** or **above** if needed.\n * Those new locations are in line with the Android `scoped storage` - so your application won't\n * lose write permission to those directories in the future.\n *\n * This method does nothing if:\n * - app is running on **iOS**, **web** or **Android below R**\n * - app has **write permission** to the album folder\n *\n * The migration is possible when the album contains only compatible files types.\n * For instance, movies and pictures are compatible with each other, but music and pictures are not.\n * If automatic migration isn't possible, the function rejects.\n * In that case, you can use methods from the `expo-file-system` to migrate all your files manually.\n *\n * # Why do you need to migrate files?\n * __Android R__ introduced a lot of changes in the storage system. Now applications can't save\n * anything to the root directory. The only available locations are from the `MediaStore` API.\n * Unfortunately, the media library stored albums in folders for which, because of those changes,\n * the application doesn't have permissions anymore. However, it doesn't mean you need to migrate\n * all your albums. If your application doesn't add assets to albums, you don't have to migrate.\n * Everything will work as it used to. You can read more about scoped storage in [the Android documentation](https://developer.android.com/about/versions/11/privacy/storage).\n *\n * @param album An [Album](#album) or its ID.\n * @return A promise which fulfils to `void`.\n */\nexport async function migrateAlbumIfNeededAsync(album: AlbumRef): Promise<void> {\n if (!MediaLibrary.migrateAlbumIfNeededAsync) {\n return;\n }\n\n return await MediaLibrary.migrateAlbumIfNeededAsync(getId(album));\n}\n\n// @needsAudit\n/**\n * Checks if the album should be migrated to a different location. In other words, it checks if the\n * application has the write permission to the album folder. If not, it returns `true`, otherwise `false`.\n * > Note: For **Android below R**, **web** or **iOS**, this function always returns `false`.\n * @param album An [Album](#album) or its ID.\n * @return Returns a promise which fulfils with `true` if the album should be migrated.\n */\nexport async function albumNeedsMigrationAsync(album: AlbumRef): Promise<boolean> {\n if (!MediaLibrary.albumNeedsMigrationAsync) {\n return false;\n }\n\n return await MediaLibrary.albumNeedsMigrationAsync(getId(album));\n}\n"]}
1
+ {"version":3,"file":"MediaLibrary.js","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n PermissionResponse as EXPermissionResponse,\n PermissionStatus,\n PermissionExpiration,\n PermissionHookOptions,\n createPermissionHook,\n UnavailabilityError,\n EventSubscription,\n} from 'expo-modules-core';\nimport { Platform } from 'react-native';\n\nimport MediaLibrary from './ExpoMediaLibrary';\n\nconst isExpoGo = typeof expo !== 'undefined' && globalThis.expo?.modules?.ExpoGo;\n\nlet loggedExpoGoWarning = false;\n\nif (isExpoGo && !loggedExpoGoWarning) {\n console.warn(\n 'Due to changes in Androids permission requirements, Expo Go can no longer provide full access to the media library. To test the full functionality of this module, you can create a development build. https://docs.expo.dev/develop/development-builds/create-a-build'\n );\n loggedExpoGoWarning = true;\n}\n\n// @needsAudit\nexport type PermissionResponse = EXPermissionResponse & {\n /**\n * Indicates if your app has access to the whole or only part of the photo library. Possible values are:\n * - `'all'` if the user granted your app access to the whole photo library\n * - `'limited'` if the user granted your app access only to selected photos (only available on Android API 14+ and iOS 14.0+)\n * - `'none'` if user denied or hasn't yet granted the permission\n */\n accessPrivileges?: 'all' | 'limited' | 'none';\n};\n\n/**\n * Determines the type of media that the app will ask the OS to get access to.\n * @platform android 13+\n */\nexport type GranularPermission = 'audio' | 'photo' | 'video';\n\nexport type MediaTypeValue = 'audio' | 'photo' | 'video' | 'unknown' | 'pairedVideo';\n\n/**\n * Represents the possible types of media that the app will ask the OS to get access to when calling [`presentPermissionsPickerAsync()`](#medialibrarypresentpermissionspickerasyncmediatypes).\n * @platform android 14+\n * */\nexport type MediaTypeFilter = 'photo' | 'video';\n\nexport type SortByKey =\n | 'default'\n | 'mediaType'\n | 'width'\n | 'height'\n | 'creationTime'\n | 'modificationTime'\n | 'duration';\nexport type SortByValue = [SortByKey, boolean] | SortByKey;\n\nexport type MediaTypeObject = {\n audio: 'audio';\n photo: 'photo';\n video: 'video';\n unknown: 'unknown';\n};\n\nexport type SortByObject = {\n default: 'default';\n mediaType: 'mediaType';\n width: 'width';\n height: 'height';\n creationTime: 'creationTime';\n modificationTime: 'modificationTime';\n duration: 'duration';\n};\n\n// @needsAudit\nexport type Asset = {\n /**\n * Internal ID that represents an asset.\n */\n id: string;\n /**\n * Filename of the asset.\n */\n filename: string;\n /**\n * URI that points to the asset. `ph://*` (iOS), `file://*` (Android)\n */\n uri: string;\n /**\n * Media type.\n */\n mediaType: MediaTypeValue;\n /**\n * An array of media subtypes.\n * @platform ios\n */\n mediaSubtypes?: MediaSubtype[];\n /**\n * Width of the image or video.\n */\n width: number;\n /**\n * Height of the image or video.\n */\n height: number;\n /**\n * File creation timestamp.\n */\n creationTime: number;\n /**\n * Last modification timestamp.\n */\n modificationTime: number;\n /**\n * Duration of the video or audio asset in seconds.\n */\n duration: number;\n /**\n * Album ID that the asset belongs to.\n * @platform android\n */\n albumId?: string;\n};\n\n// @needsAudit\nexport type AssetInfo = Asset & {\n /**\n * Local URI for the asset.\n */\n localUri?: string;\n /**\n * GPS location if available.\n */\n location?: Location;\n /**\n * EXIF metadata associated with the image.\n */\n exif?: object;\n /**\n * Whether the asset is marked as favorite.\n * @platform ios\n */\n isFavorite?: boolean;\n /**\n * This field is available only if flag `shouldDownloadFromNetwork` is set to `false`.\n * Whether the asset is stored on the network (iCloud on iOS).\n * @platform ios\n */\n isNetworkAsset?: boolean; //iOS only\n /**\n * Display orientation of the image. Orientation is available only for assets whose\n * `mediaType` is `MediaType.photo`. Value will range from 1 to 8, see [EXIF orientation specification](http://sylvana.net/jpegcrop/exif_orientation.html)\n * for more details.\n * @platform ios\n */\n orientation?: number;\n /**\n * Contains information about the video paired with the image file.\n * This field is available if the `mediaType` is `\"photo\"`, and the `mediaSubtypes` includes `\"livePhoto\"`.\n * @platform ios\n */\n pairedVideoAsset?: Asset | null;\n};\n\n/**\n * Constants identifying specific variations of asset media, such as panorama or screenshot photos,\n * and time-lapse or high-frame-rate video. Maps to [these values](https://developer.apple.com/documentation/photokit/phassetmediasubtype#1603888).\n * */\nexport type MediaSubtype =\n | 'depthEffect'\n | 'hdr'\n | 'highFrameRate'\n | 'livePhoto'\n | 'panorama'\n | 'screenshot'\n | 'stream'\n | 'timelapse';\n\n// @needsAudit\nexport type MediaLibraryAssetInfoQueryOptions = {\n /**\n * Whether allow the asset to be downloaded from network. Only available in iOS with iCloud assets.\n * @default true\n */\n shouldDownloadFromNetwork?: boolean;\n};\n\n// @needsAudit\nexport type MediaLibraryAssetsChangeEvent = {\n /**\n * Whether the media library's changes could be described as \"incremental changes\".\n * `true` indicates the changes are described by the `insertedAssets`, `deletedAssets` and\n * `updatedAssets` values. `false` indicates that the scope of changes is too large and you\n * should perform a full assets reload (eg. a user has changed access to individual assets in the\n * media library).\n */\n hasIncrementalChanges: boolean;\n /**\n * Available only if `hasIncrementalChanges` is `true`.\n * Array of [`Asset`](#asset)s that have been inserted to the library.\n */\n insertedAssets?: Asset[];\n /**\n * Available only if `hasIncrementalChanges` is `true`.\n * Array of [`Asset`](#asset)s that have been deleted from the library.\n */\n deletedAssets?: Asset[];\n /**\n * Available only if `hasIncrementalChanges` is `true`.\n * Array of [`Asset`](#asset)s that have been updated or completed downloading from network\n * storage (iCloud on iOS).\n */\n updatedAssets?: Asset[];\n};\n\n// @docsMissing\nexport type Location = {\n latitude: number;\n longitude: number;\n};\n\n// @needsAudit\nexport type Album = {\n /**\n * Album ID.\n */\n id: string;\n /**\n * Album title.\n */\n title: string;\n /**\n * Estimated number of assets in the album.\n */\n assetCount: number;\n /**\n * The type of the assets album.\n * @platform ios\n */\n type?: AlbumType;\n /**\n * Apply only to albums whose type is `'moment'`. Earliest creation timestamp of all\n * assets in the moment.\n * @platform ios\n */\n startTime: number;\n /**\n * Apply only to albums whose type is `'moment'`. Latest creation timestamp of all\n * assets in the moment.\n * @platform ios\n */\n endTime: number;\n /**\n * Apply only to albums whose type is `'moment'`. Approximated location of all\n * assets in the moment.\n * @platform ios\n */\n approximateLocation?: Location;\n /**\n * Apply only to albums whose type is `'moment'`. Names of locations grouped\n * in the moment.\n * @platform ios\n */\n locationNames?: string[];\n};\n\n// @docsMissing\nexport type AlbumType = 'album' | 'moment' | 'smartAlbum';\n\n// @docsMissing\nexport type AlbumsOptions = {\n includeSmartAlbums?: boolean;\n};\n\n// @needsAudit\nexport type AssetsOptions = {\n /**\n * The maximum number of items on a single page.\n * @default 20\n */\n first?: number;\n /**\n * Asset ID of the last item returned on the previous page. To get the ID of the next page,\n * pass [`endCursor`](#pagedinfo) as its value.\n */\n after?: AssetRef;\n /**\n * [Album](#album) or its ID to get assets from specific album.\n */\n album?: AlbumRef;\n /**\n * An array of [`SortByValue`](#sortbyvalue)s or a single `SortByValue` value. By default, all\n * keys are sorted in descending order, however you can also pass a pair `[key, ascending]` where\n * the second item is a `boolean` value that means whether to use ascending order. Note that if\n * the `SortBy.default` key is used, then `ascending` argument will not matter. Earlier items have\n * higher priority when sorting out the results.\n * If empty, this method uses the default sorting that is provided by the platform.\n */\n sortBy?: SortByValue[] | SortByValue;\n /**\n * An array of [MediaTypeValue](#mediatypevalue)s or a single `MediaTypeValue`.\n * @default MediaType.photo\n */\n mediaType?: MediaTypeValue[] | MediaTypeValue;\n /**\n * `Date` object or Unix timestamp in milliseconds limiting returned assets only to those that\n * were created after this date.\n */\n createdAfter?: Date | number;\n /**\n * Similarly as `createdAfter`, but limits assets only to those that were created before specified\n * date.\n */\n createdBefore?: Date | number;\n};\n\n// @needsAudit\nexport type PagedInfo<T> = {\n /**\n * A page of [`Asset`](#asset)s fetched by the query.\n */\n assets: T[];\n /**\n * ID of the last fetched asset. It should be passed as `after` option in order to get the\n * next page.\n */\n endCursor: string;\n /**\n * Whether there are more assets to fetch.\n */\n hasNextPage: boolean;\n /**\n * Estimated total number of assets that match the query.\n */\n totalCount: number;\n};\n\n// @docsMissing\nexport type AssetRef = Asset | string;\n\n// @docsMissing\nexport type AlbumRef = Album | string;\n\nexport {\n PermissionStatus,\n PermissionExpiration,\n EXPermissionResponse,\n PermissionHookOptions,\n EventSubscription as Subscription,\n};\n\nfunction arrayize(item: any): any[] {\n if (Array.isArray(item)) {\n return item;\n }\n return item ? [item] : [];\n}\n\nfunction getId(ref: any): string | undefined {\n if (typeof ref === 'string') {\n return ref;\n }\n return ref ? ref.id : undefined;\n}\n\nfunction checkAssetIds(assetIds: any): void {\n if (assetIds.some((id) => !id || typeof id !== 'string')) {\n throw new Error('Asset ID must be a string!');\n }\n}\n\nfunction checkAlbumIds(albumIds: any): void {\n if (albumIds.some((id) => !id || typeof id !== 'string')) {\n throw new Error('Album ID must be a string!');\n }\n}\n\nfunction checkMediaType(mediaType: any): void {\n if (Object.values(MediaType).indexOf(mediaType) === -1) {\n throw new Error(`Invalid mediaType: ${mediaType}`);\n }\n}\n\nfunction checkSortBy(sortBy: any): void {\n if (Array.isArray(sortBy)) {\n checkSortByKey(sortBy[0]);\n\n if (typeof sortBy[1] !== 'boolean') {\n throw new Error('Invalid sortBy array argument. Second item must be a boolean!');\n }\n } else {\n checkSortByKey(sortBy);\n }\n}\n\nfunction checkSortByKey(sortBy: any): void {\n if (Object.values(SortBy).indexOf(sortBy) === -1) {\n throw new Error(`Invalid sortBy key: ${sortBy}`);\n }\n}\n\nfunction sortByOptionToString(sortBy: any) {\n if (Array.isArray(sortBy)) {\n return `${sortBy[0]} ${sortBy[1] ? 'ASC' : 'DESC'}`;\n }\n return `${sortBy} DESC`;\n}\n\nfunction dateToNumber(value?: Date | number): number | undefined {\n return value instanceof Date ? value.getTime() : value;\n}\n\n// @needsAudit\n/**\n * Possible media types.\n */\nexport const MediaType: MediaTypeObject = MediaLibrary.MediaType;\n\n// @needsAudit\n/**\n * Supported keys that can be used to sort `getAssetsAsync` results.\n */\nexport const SortBy: SortByObject = MediaLibrary.SortBy;\n\n// @needsAudit\n/**\n * Returns whether the Media Library API is enabled on the current device.\n * @return A promise which fulfils with a `boolean`, indicating whether the Media Library API is\n * available on the current device.\n */\nexport async function isAvailableAsync(): Promise<boolean> {\n return !!MediaLibrary && 'getAssetsAsync' in MediaLibrary;\n}\n\n// @needsAudit @docsMissing\n/**\n * Asks the user to grant permissions for accessing media in user's media library.\n * @param writeOnly\n * @param granularPermissions - A list of [`GranularPermission`](#granularpermission) values. This parameter has an\n * effect only on Android 13 and newer. By default, `expo-media-library` will ask for all possible permissions.\n * @return A promise that fulfils with [`PermissionResponse`](#permissionresponse) object.\n */\nexport async function requestPermissionsAsync(\n writeOnly: boolean = false,\n granularPermissions?: GranularPermission[]\n): Promise<PermissionResponse> {\n if (!MediaLibrary.requestPermissionsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'requestPermissionsAsync');\n }\n if (Platform.OS === 'android') {\n return await MediaLibrary.requestPermissionsAsync(writeOnly, granularPermissions);\n }\n return await MediaLibrary.requestPermissionsAsync(writeOnly);\n}\n\n// @needsAudit @docsMissing\n/**\n * Checks user's permissions for accessing media library.\n * @param writeOnly\n * @param granularPermissions - A list of [`GranularPermission`](#granularpermission) values. This parameter has\n * an effect only on Android 13 and newer. By default, `expo-media-library` will ask for all possible permissions.\n * @return A promise that fulfils with [`PermissionResponse`](#permissionresponse) object.\n */\nexport async function getPermissionsAsync(\n writeOnly: boolean = false,\n granularPermissions?: GranularPermission[]\n): Promise<PermissionResponse> {\n if (!MediaLibrary.getPermissionsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getPermissionsAsync');\n }\n if (Platform.OS === 'android') {\n return await MediaLibrary.getPermissionsAsync(writeOnly, granularPermissions);\n }\n return await MediaLibrary.getPermissionsAsync(writeOnly);\n}\n\n// @needsAudit\n/**\n * Check or request permissions to access the media library.\n * This uses both `requestPermissionsAsync` and `getPermissionsAsync` to interact with the permissions.\n *\n * @example\n * ```ts\n * const [permissionResponse, requestPermission] = MediaLibrary.usePermissions();\n * ```\n */\nexport const usePermissions = createPermissionHook<\n PermissionResponse,\n { writeOnly?: boolean; granularPermissions?: GranularPermission[] }\n>({\n // TODO(cedric): permission requesters should have an options param or a different requester\n getMethod: (options) => getPermissionsAsync(options?.writeOnly, options?.granularPermissions),\n requestMethod: (options) =>\n requestPermissionsAsync(options?.writeOnly, options?.granularPermissions),\n});\n\n// @needsAudit\n/**\n * Allows the user to update the assets that your app has access to.\n * The system modal is only displayed if the user originally allowed only `limited` access to their\n * media library, otherwise this method is a no-op.\n * @param mediaTypes Limits the type(s) of media that the user will be granting access to. By default, a list that shows both photos and videos is presented.\n *\n * @return A promise that either rejects if the method is unavailable, or resolves to `void`.\n * > __Note:__ This method doesn't inform you if the user changes which assets your app has access to.\n * That information is only exposed by iOS, and to obtain it, you need to subscribe for updates to the user's media library using [`addListener()`](#medialibraryaddlistenerlistener).\n * If `hasIncrementalChanges` is `false`, the user changed their permissions.\n *\n * @platform android 14+\n * @platform ios\n */\nexport async function presentPermissionsPickerAsync(\n mediaTypes: MediaTypeFilter[] = ['photo', 'video']\n): Promise<void> {\n if (Platform.OS === 'android' && isExpoGo) {\n throw new UnavailabilityError(\n 'MediaLibrary',\n 'presentPermissionsPickerAsync is unavailable in Expo Go'\n );\n }\n if (Platform.OS === 'android' && Platform.Version >= 34) {\n await MediaLibrary.requestPermissionsAsync(false, mediaTypes);\n return;\n }\n if (!MediaLibrary.presentPermissionsPickerAsync) {\n throw new UnavailabilityError('MediaLibrary', 'presentPermissionsPickerAsync');\n }\n return await MediaLibrary.presentPermissionsPickerAsync();\n}\n\n// @needsAudit\n/**\n * Creates an asset from existing file. The most common use case is to save a picture taken by [Camera](./camera).\n * This method requires `CAMERA_ROLL` permission.\n *\n * @example\n * ```js\n * const { uri } = await Camera.takePictureAsync();\n * const asset = await MediaLibrary.createAssetAsync(uri);\n * ```\n * @param localUri A URI to the image or video file. It must contain an extension. On Android it\n * must be a local path, so it must start with `file:///`\n * @return A promise which fulfils with an object representing an [`Asset`](#asset).\n */\nexport async function createAssetAsync(localUri: string): Promise<Asset> {\n if (!MediaLibrary.createAssetAsync) {\n throw new UnavailabilityError('MediaLibrary', 'createAssetAsync');\n }\n\n if (!localUri || typeof localUri !== 'string') {\n throw new Error('Invalid argument \"localUri\". It must be a string!');\n }\n const asset = await MediaLibrary.createAssetAsync(localUri);\n\n if (Array.isArray(asset)) {\n // Android returns an array with asset, we need to pick the first item\n return asset[0];\n }\n return asset;\n}\n\n// @needsAudit\n/**\n * Saves the file at given `localUri` to the user's media library. Unlike [`createAssetAsync()`](#medialibrarycreateassetasynclocaluri),\n * This method doesn't return created asset.\n * On __iOS 11+__, it's possible to use this method without asking for `CAMERA_ROLL` permission,\n * however then yours `Info.plist` should have `NSPhotoLibraryAddUsageDescription` key.\n * @param localUri A URI to the image or video file. It must contain an extension. On Android it\n * must be a local path, so it must start with `file:///`.\n */\nexport async function saveToLibraryAsync(localUri: string): Promise<void> {\n if (!MediaLibrary.saveToLibraryAsync) {\n throw new UnavailabilityError('MediaLibrary', 'saveToLibraryAsync');\n }\n return await MediaLibrary.saveToLibraryAsync(localUri);\n}\n\n// @needsAudit\n/**\n * Adds array of assets to the album.\n *\n * On Android, by default it copies assets from the current album to provided one, however it's also\n * possible to move them by passing `false` as `copyAssets` argument. In case they're copied you\n * should keep in mind that `getAssetsAsync` will return duplicated assets.\n * @param assets An array of [Asset](#asset) or their IDs.\n * @param album An [Album](#album) or its ID.\n * @param copy __Android only.__ Whether to copy assets to the new album instead of move them.\n * Defaults to `true`.\n * @return Returns promise which fulfils with `true` if the assets were successfully added to\n * the album.\n */\nexport async function addAssetsToAlbumAsync(\n assets: AssetRef[] | AssetRef,\n album: AlbumRef,\n copy: boolean = true\n): Promise<boolean> {\n if (!MediaLibrary.addAssetsToAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'addAssetsToAlbumAsync');\n }\n\n const assetIds = arrayize(assets).map(getId);\n const albumId = getId(album);\n\n checkAssetIds(assetIds);\n\n if (!albumId || typeof albumId !== 'string') {\n throw new Error('Invalid album ID. It must be a string!');\n }\n\n if (Platform.OS === 'ios') {\n return await MediaLibrary.addAssetsToAlbumAsync(assetIds, albumId);\n }\n return await MediaLibrary.addAssetsToAlbumAsync(assetIds, albumId, !!copy);\n}\n\n// @needsAudit\n/**\n * Removes given assets from album.\n *\n * On Android, album will be automatically deleted if there are no more assets inside.\n * @param assets An array of [Asset](#asset) or their IDs.\n * @param album An [Album](#album) or its ID.\n * @return Returns promise which fulfils with `true` if the assets were successfully removed from\n * the album.\n */\nexport async function removeAssetsFromAlbumAsync(\n assets: AssetRef[] | AssetRef,\n album: AlbumRef\n): Promise<boolean> {\n if (!MediaLibrary.removeAssetsFromAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'removeAssetsFromAlbumAsync');\n }\n\n const assetIds = arrayize(assets).map(getId);\n const albumId = getId(album);\n\n checkAssetIds(assetIds);\n return await MediaLibrary.removeAssetsFromAlbumAsync(assetIds, albumId);\n}\n\n// @needsAudit\n/**\n * Deletes assets from the library. On iOS it deletes assets from all albums they belong to, while\n * on Android it keeps all copies of them (album is strictly connected to the asset). Also, there is\n * additional dialog on iOS that requires user to confirm this action.\n * @param assets An array of [Asset](#asset) or their IDs.\n * @return Returns promise which fulfils with `true` if the assets were successfully deleted.\n */\nexport async function deleteAssetsAsync(assets: AssetRef[] | AssetRef): Promise<boolean> {\n if (!MediaLibrary.deleteAssetsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'deleteAssetsAsync');\n }\n\n const assetIds = arrayize(assets).map(getId);\n\n checkAssetIds(assetIds);\n return await MediaLibrary.deleteAssetsAsync(assetIds);\n}\n\n// @needsAudit\n/**\n * Provides more information about an asset, including GPS location, local URI and EXIF metadata.\n * @param asset An [Asset](#asset) or its ID.\n * @param options\n * @return An [AssetInfo](#assetinfo) object, which is an `Asset` extended by an additional fields.\n */\nexport async function getAssetInfoAsync(\n asset: AssetRef,\n options: MediaLibraryAssetInfoQueryOptions = { shouldDownloadFromNetwork: true }\n): Promise<AssetInfo> {\n if (!MediaLibrary.getAssetInfoAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAssetInfoAsync');\n }\n\n const assetId = getId(asset);\n\n checkAssetIds([assetId]);\n\n const assetInfo = await MediaLibrary.getAssetInfoAsync(assetId, options);\n\n if (Array.isArray(assetInfo)) {\n // Android returns an array with asset info, we need to pick the first item\n return assetInfo[0];\n }\n return assetInfo;\n}\n\n// @needsAudit\n/**\n * Queries for user-created albums in media gallery.\n * @return A promise which fulfils with an array of [`Album`](#asset)s. Depending on Android version,\n * root directory of your storage may be listed as album titled `\"0\"` or unlisted at all.\n */\nexport async function getAlbumsAsync({ includeSmartAlbums = false }: AlbumsOptions = {}): Promise<\n Album[]\n> {\n if (!MediaLibrary.getAlbumsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAlbumsAsync');\n }\n return await MediaLibrary.getAlbumsAsync({ includeSmartAlbums });\n}\n\n// @needsAudit\n/**\n * Queries for an album with a specific name.\n * @param title Name of the album to look for.\n * @return An object representing an [`Album`](#album), if album with given name exists, otherwise\n * returns `null`.\n */\nexport async function getAlbumAsync(title: string): Promise<Album> {\n if (!MediaLibrary.getAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAlbumAsync');\n }\n if (typeof title !== 'string') {\n throw new Error('Album title must be a string!');\n }\n return await MediaLibrary.getAlbumAsync(title);\n}\n\n// @needsAudit\n/**\n * Creates an album with given name and initial asset. The asset parameter is required on Android,\n * since it's not possible to create empty album on this platform. On Android, by default it copies\n * given asset from the current album to the new one, however it's also possible to move it by\n * passing `false` as `copyAsset` argument.\n * In case it's copied you should keep in mind that `getAssetsAsync` will return duplicated asset.\n * @param albumName Name of the album to create.\n * @param asset An [Asset](#asset) or its ID (required on Android).\n * @param copyAsset __Android Only.__ Whether to copy asset to the new album instead of move it.\n * Defaults to `true`.\n * @return Newly created [`Album`](#album).\n */\nexport async function createAlbumAsync(\n albumName: string,\n asset?: AssetRef,\n copyAsset: boolean = true\n): Promise<Album> {\n if (!MediaLibrary.createAlbumAsync) {\n throw new UnavailabilityError('MediaLibrary', 'createAlbumAsync');\n }\n\n const assetId = getId(asset);\n\n if (Platform.OS === 'android' && (typeof assetId !== 'string' || assetId.length === 0)) {\n // it's not possible to create empty album on Android, so initial asset must be provided\n throw new Error('MediaLibrary.createAlbumAsync must be called with an asset on Android.');\n }\n if (!albumName || typeof albumName !== 'string') {\n throw new Error('Invalid argument \"albumName\". It must be a string!');\n }\n if (assetId != null && typeof assetId !== 'string') {\n throw new Error('Asset ID must be a string!');\n }\n\n if (Platform.OS === 'ios') {\n return await MediaLibrary.createAlbumAsync(albumName, assetId);\n }\n return await MediaLibrary.createAlbumAsync(albumName, assetId, !!copyAsset);\n}\n\n// @needsAudit\n/**\n * Deletes given albums from the library. On Android by default it deletes assets belonging to given\n * albums from the library. On iOS it doesn't delete these assets, however it's possible to do by\n * passing `true` as `deleteAssets`.\n * @param albums An array of [`Album`](#asset)s or their IDs.\n * @param assetRemove __iOS Only.__ Whether to also delete assets belonging to given albums.\n * Defaults to `false`.\n * @return Returns a promise which fulfils with `true` if the albums were successfully deleted from\n * the library.\n */\nexport async function deleteAlbumsAsync(\n albums: AlbumRef[] | AlbumRef,\n assetRemove: boolean = false\n): Promise<boolean> {\n if (!MediaLibrary.deleteAlbumsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'deleteAlbumsAsync');\n }\n\n const albumIds = arrayize(albums).map(getId);\n\n checkAlbumIds(albumIds);\n if (Platform.OS === 'android') {\n return await MediaLibrary.deleteAlbumsAsync(albumIds);\n }\n return await MediaLibrary.deleteAlbumsAsync(albumIds, !!assetRemove);\n}\n\n// @needsAudit\n/**\n * Fetches a page of assets matching the provided criteria.\n * @param assetsOptions\n * @return A promise that fulfils with to [`PagedInfo`](#pagedinfo) object with array of [`Asset`](#asset)s.\n */\nexport async function getAssetsAsync(assetsOptions: AssetsOptions = {}): Promise<PagedInfo<Asset>> {\n if (!MediaLibrary.getAssetsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getAssetsAsync');\n }\n\n const { first, after, album, sortBy, mediaType, createdAfter, createdBefore } = assetsOptions;\n\n const options = {\n first: first == null ? 20 : first,\n after: getId(after),\n album: getId(album),\n sortBy: arrayize(sortBy),\n mediaType: arrayize(mediaType || [MediaType.photo]),\n createdAfter: dateToNumber(createdAfter),\n createdBefore: dateToNumber(createdBefore),\n };\n\n if (first != null && typeof options.first !== 'number') {\n throw new Error('Option \"first\" must be a number!');\n }\n if (after != null && typeof options.after !== 'string') {\n throw new Error('Option \"after\" must be a string!');\n }\n if (album != null && typeof options.album !== 'string') {\n throw new Error('Option \"album\" must be a string!');\n }\n\n if (after != null && Platform.OS === 'android' && isNaN(parseInt(getId(after) as string, 10))) {\n throw new Error('Option \"after\" must be a valid ID!');\n }\n\n if (first != null && first < 0) {\n throw new Error('Option \"first\" must be a positive integer!');\n }\n\n options.sortBy.forEach(checkSortBy);\n options.mediaType.forEach(checkMediaType);\n options.sortBy = options.sortBy.map(sortByOptionToString);\n\n return await MediaLibrary.getAssetsAsync(options);\n}\n\n// @needsAudit\n/**\n * Subscribes for updates in user's media library.\n * @param listener A callback that is fired when any assets have been inserted or deleted from the\n * library. On Android it's invoked with an empty object. On iOS, it's invoked with [`MediaLibraryAssetsChangeEvent`](#medialibraryassetschangeevent)\n * object.\n *\n * Additionally, only on iOS, the listener is also invoked when the user changes access to individual assets in the media library\n * using `presentPermissionsPickerAsync()`.\n * @return An [`Subscription`](#subscription) object that you can call `remove()` on when you would\n * like to unsubscribe the listener.\n */\nexport function addListener(\n listener: (event: MediaLibraryAssetsChangeEvent) => void\n): EventSubscription {\n return MediaLibrary.addListener(MediaLibrary.CHANGE_LISTENER_NAME, listener);\n}\n\n// @docsMissing\nexport function removeSubscription(subscription: EventSubscription): void {\n subscription.remove();\n}\n\n// @needsAudit\n/**\n * Removes all listeners.\n */\nexport function removeAllListeners(): void {\n MediaLibrary.removeAllListeners(MediaLibrary.CHANGE_LISTENER_NAME);\n}\n\n// @needsAudit\n/**\n * Fetches a list of moments, which is a group of assets taken around the same place\n * and time.\n * @return An array of [albums](#album) whose type is `moment`.\n * @platform ios\n */\nexport async function getMomentsAsync() {\n if (!MediaLibrary.getMomentsAsync) {\n throw new UnavailabilityError('MediaLibrary', 'getMomentsAsync');\n }\n\n return await MediaLibrary.getMomentsAsync();\n}\n\n// @needsAudit\n/**\n * Moves album content to the special media directories on **Android R** or **above** if needed.\n * Those new locations are in line with the Android `scoped storage` - so your application won't\n * lose write permission to those directories in the future.\n *\n * This method does nothing if:\n * - app is running on **iOS**, **web** or **Android below R**\n * - app has **write permission** to the album folder\n *\n * The migration is possible when the album contains only compatible files types.\n * For instance, movies and pictures are compatible with each other, but music and pictures are not.\n * If automatic migration isn't possible, the function rejects.\n * In that case, you can use methods from the `expo-file-system` to migrate all your files manually.\n *\n * # Why do you need to migrate files?\n * __Android R__ introduced a lot of changes in the storage system. Now applications can't save\n * anything to the root directory. The only available locations are from the `MediaStore` API.\n * Unfortunately, the media library stored albums in folders for which, because of those changes,\n * the application doesn't have permissions anymore. However, it doesn't mean you need to migrate\n * all your albums. If your application doesn't add assets to albums, you don't have to migrate.\n * Everything will work as it used to. You can read more about scoped storage in [the Android documentation](https://developer.android.com/about/versions/11/privacy/storage).\n *\n * @param album An [Album](#album) or its ID.\n * @return A promise which fulfils to `void`.\n */\nexport async function migrateAlbumIfNeededAsync(album: AlbumRef): Promise<void> {\n if (!MediaLibrary.migrateAlbumIfNeededAsync) {\n return;\n }\n\n return await MediaLibrary.migrateAlbumIfNeededAsync(getId(album));\n}\n\n// @needsAudit\n/**\n * Checks if the album should be migrated to a different location. In other words, it checks if the\n * application has the write permission to the album folder. If not, it returns `true`, otherwise `false`.\n * > Note: For **Android below R**, **web** or **iOS**, this function always returns `false`.\n * @param album An [Album](#album) or its ID.\n * @return Returns a promise which fulfils with `true` if the album should be migrated.\n */\nexport async function albumNeedsMigrationAsync(album: AlbumRef): Promise<boolean> {\n if (!MediaLibrary.albumNeedsMigrationAsync) {\n return false;\n }\n\n return await MediaLibrary.albumNeedsMigrationAsync(getId(album));\n}\n"]}
@@ -11,7 +11,8 @@ Pod::Spec.new do |s|
11
11
  s.author = package['author']
12
12
  s.homepage = package['homepage']
13
13
  s.platforms = {
14
- :ios => '15.1'
14
+ :ios => '15.1',
15
+ :tvos => '15.1'
15
16
  }
16
17
  s.source = { git: 'https://github.com/expo/expo.git' }
17
18
  s.static_framework = true
@@ -65,10 +65,12 @@ public class MediaLibraryModule: Module, PhotoLibraryObserverHandler {
65
65
  }
66
66
 
67
67
  AsyncFunction("presentPermissionsPickerAsync") {
68
+ #if os(iOS)
68
69
  guard let vc = appContext?.utilities?.currentViewController() else {
69
70
  return
70
71
  }
71
72
  PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: vc)
73
+ #endif
72
74
  }.runOnQueue(.main)
73
75
 
74
76
  AsyncFunction("createAssetAsync") { (uri: URL, promise: Promise) in
@@ -110,6 +112,7 @@ public class MediaLibraryModule: Module, PhotoLibraryObserverHandler {
110
112
  }
111
113
 
112
114
  AsyncFunction("saveToLibraryAsync") { (localUrl: URL, promise: Promise) in
115
+ #if os(iOS)
113
116
  if Bundle.main.infoDictionary?["NSPhotoLibraryAddUsageDescription"] == nil {
114
117
  throw MissingPListKeyException("NSPhotoLibraryAddUsageDescription")
115
118
  }
@@ -155,6 +158,7 @@ public class MediaLibraryModule: Module, PhotoLibraryObserverHandler {
155
158
  promise.reject(SaveVideoException())
156
159
  return
157
160
  }
161
+ #endif
158
162
 
159
163
  promise.reject(UnsupportedAssetException())
160
164
  }
@@ -6,6 +6,7 @@ typealias SaveToLibraryCallback = (Any?, Error?) -> Void
6
6
  class SaveToLibraryDelegate: NSObject {
7
7
  var callback: SaveToLibraryCallback?
8
8
 
9
+ #if os(iOS)
9
10
  func writeImage(_ image: UIImage, withCallback callback: @escaping SaveToLibraryCallback) {
10
11
  self.callback = callback
11
12
  UIImageWriteToSavedPhotosAlbum(
@@ -49,4 +50,5 @@ class SaveToLibraryDelegate: NSObject {
49
50
  func triggerCallback(_ asset: Any?, with error: Error?) {
50
51
  callback?(asset, error)
51
52
  }
53
+ #endif
52
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-media-library",
3
- "version": "17.1.0-canary-20250131-5c4e588",
3
+ "version": "17.1.0-canary-20250219-4a5dade",
4
4
  "description": "Provides access to user's media library.",
5
5
  "main": "build/MediaLibrary.js",
6
6
  "types": "build/MediaLibrary.d.ts",
@@ -38,10 +38,10 @@
38
38
  "preset": "expo-module-scripts"
39
39
  },
40
40
  "devDependencies": {
41
- "expo-module-scripts": "4.0.4-canary-20250131-5c4e588"
41
+ "expo-module-scripts": "4.0.5-canary-20250219-4a5dade"
42
42
  },
43
43
  "peerDependencies": {
44
- "expo": "53.0.0-canary-20250131-5c4e588",
44
+ "expo": "53.0.0-canary-20250219-4a5dade",
45
45
  "react-native": "*"
46
46
  },
47
47
  "codegenConfig": {
@@ -53,5 +53,6 @@
53
53
  "RCTImageURLLoader": "MediaLibraryImageLoader"
54
54
  }
55
55
  }
56
- }
56
+ },
57
+ "gitHead": "4a5daded61d3d8b9d501059039ac74c09c25675b"
57
58
  }
@@ -11,6 +11,17 @@ import { Platform } from 'react-native';
11
11
 
12
12
  import MediaLibrary from './ExpoMediaLibrary';
13
13
 
14
+ const isExpoGo = typeof expo !== 'undefined' && globalThis.expo?.modules?.ExpoGo;
15
+
16
+ let loggedExpoGoWarning = false;
17
+
18
+ if (isExpoGo && !loggedExpoGoWarning) {
19
+ console.warn(
20
+ 'Due to changes in Androids permission requirements, Expo Go can no longer provide full access to the media library. To test the full functionality of this module, you can create a development build. https://docs.expo.dev/develop/development-builds/create-a-build'
21
+ );
22
+ loggedExpoGoWarning = true;
23
+ }
24
+
14
25
  // @needsAudit
15
26
  export type PermissionResponse = EXPermissionResponse & {
16
27
  /**
@@ -433,7 +444,7 @@ export async function isAvailableAsync(): Promise<boolean> {
433
444
  */
434
445
  export async function requestPermissionsAsync(
435
446
  writeOnly: boolean = false,
436
- granularPermissions: GranularPermission[] = ['audio', 'photo', 'video']
447
+ granularPermissions?: GranularPermission[]
437
448
  ): Promise<PermissionResponse> {
438
449
  if (!MediaLibrary.requestPermissionsAsync) {
439
450
  throw new UnavailabilityError('MediaLibrary', 'requestPermissionsAsync');
@@ -454,7 +465,7 @@ export async function requestPermissionsAsync(
454
465
  */
455
466
  export async function getPermissionsAsync(
456
467
  writeOnly: boolean = false,
457
- granularPermissions: GranularPermission[] = ['audio', 'photo', 'video']
468
+ granularPermissions?: GranularPermission[]
458
469
  ): Promise<PermissionResponse> {
459
470
  if (!MediaLibrary.getPermissionsAsync) {
460
471
  throw new UnavailabilityError('MediaLibrary', 'getPermissionsAsync');
@@ -503,6 +514,12 @@ export const usePermissions = createPermissionHook<
503
514
  export async function presentPermissionsPickerAsync(
504
515
  mediaTypes: MediaTypeFilter[] = ['photo', 'video']
505
516
  ): Promise<void> {
517
+ if (Platform.OS === 'android' && isExpoGo) {
518
+ throw new UnavailabilityError(
519
+ 'MediaLibrary',
520
+ 'presentPermissionsPickerAsync is unavailable in Expo Go'
521
+ );
522
+ }
506
523
  if (Platform.OS === 'android' && Platform.Version >= 34) {
507
524
  await MediaLibrary.requestPermissionsAsync(false, mediaTypes);
508
525
  return;