expo-media-library 17.1.0-canary-20250320-7a205d3 → 17.1.0-canary-20250402-161f57b

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
@@ -7,6 +7,7 @@
7
7
  ### 🎉 New features
8
8
 
9
9
  - [iOS] Adding `pairedVideoAsset` for Live Photo support. ([#33274](https://github.com/expo/expo/pull/33274) by [@entiendoNull](https://github.com/entiendoNull))
10
+ - Add `album` parameter to `createAssetAsync`. ([#35686](https://github.com/expo/expo/pull/35686) by [@behenate](https://github.com/behenate))
10
11
 
11
12
  ### 🐛 Bug fixes
12
13
 
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'host.exp.exponent'
7
- version = '17.0.3'
7
+ version = '17.1.0-canary-20250402-161f57b'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.medialibrary"
11
11
  defaultConfig {
12
12
  versionCode 37
13
- versionName "17.0.3"
13
+ versionName "17.1.0-canary-20250402-161f57b"
14
14
  }
15
15
  }
16
16
 
@@ -40,7 +40,7 @@ import expo.modules.medialibrary.albums.RemoveAssetsFromAlbum
40
40
  import expo.modules.medialibrary.albums.getAssetsInAlbums
41
41
  import expo.modules.medialibrary.albums.migration.CheckIfAlbumShouldBeMigrated
42
42
  import expo.modules.medialibrary.albums.migration.MigrateAlbum
43
- import expo.modules.medialibrary.assets.CreateAsset
43
+ import expo.modules.medialibrary.assets.CreateAssetWithAlbumId
44
44
  import expo.modules.medialibrary.assets.DeleteAssets
45
45
  import expo.modules.medialibrary.assets.GetAssetInfo
46
46
  import expo.modules.medialibrary.assets.GetAssets
@@ -104,16 +104,16 @@ class MediaLibraryModule : Module() {
104
104
  AsyncFunction("saveToLibraryAsync") { localUri: String, promise: Promise ->
105
105
  throwUnlessPermissionsGranted {
106
106
  withModuleScope(promise) {
107
- CreateAsset(context, localUri, promise, false)
107
+ CreateAssetWithAlbumId(context, localUri, promise, false)
108
108
  .execute()
109
109
  }
110
110
  }
111
111
  }
112
112
 
113
- AsyncFunction("createAssetAsync") { localUri: String, promise: Promise ->
113
+ AsyncFunction("createAssetAsync") { localUri: String, albumId: String?, promise: Promise ->
114
114
  throwUnlessPermissionsGranted {
115
115
  withModuleScope(promise) {
116
- CreateAsset(context, localUri, promise)
116
+ CreateAssetWithAlbumId(context, localUri, promise, true, albumId)
117
117
  .execute()
118
118
  }
119
119
  }
@@ -9,7 +9,9 @@ import expo.modules.medialibrary.AlbumException
9
9
  import expo.modules.medialibrary.ERROR_UNABLE_TO_LOAD
10
10
  import expo.modules.medialibrary.ERROR_UNABLE_TO_LOAD_PERMISSION
11
11
  import expo.modules.medialibrary.EXTERNAL_CONTENT_URI
12
+ import expo.modules.medialibrary.MediaLibraryException
12
13
  import expo.modules.medialibrary.MediaLibraryUtils.queryPlaceholdersFor
14
+ import java.io.File
13
15
 
14
16
  /**
15
17
  * Queries for assets filtered by given `selection`.
@@ -83,3 +85,35 @@ fun getAssetsInAlbums(context: Context, vararg albumIds: String?): List<String>
83
85
  }
84
86
  return assetIds
85
87
  }
88
+
89
+ internal fun getFileOrNullByContextResolver(context: Context, selection: String, selectionArgs: Array<String>): File? {
90
+ context.contentResolver.query(
91
+ EXTERNAL_CONTENT_URI,
92
+ arrayOf(MediaColumns.DATA),
93
+ selection,
94
+ selectionArgs,
95
+ null
96
+ ).use { fileCursor ->
97
+ if (fileCursor == null) {
98
+ throw AlbumException("Could not get album. Query returns null.")
99
+ } else if (fileCursor.count == 0) {
100
+ return null
101
+ }
102
+ fileCursor.moveToNext()
103
+ val filePathColumnIndex = fileCursor.getColumnIndex(MediaStore.Images.Media.DATA)
104
+ val fileInAlbum = File(fileCursor.getString(filePathColumnIndex))
105
+
106
+ // Media store table can be corrupted. Extra check won't harm anyone.
107
+ if (!fileInAlbum.isFile && !fileInAlbum.isDirectory) {
108
+ throw MediaLibraryException()
109
+ }
110
+ return File(fileInAlbum.parent!!)
111
+ }
112
+ }
113
+
114
+ internal fun getAlbumFileOrNull(context: Context, albumId: String): File? {
115
+ val selection = "${MediaColumns.BUCKET_ID}=?"
116
+ val selectionArgs = arrayOf(albumId)
117
+
118
+ return getFileOrNullByContextResolver(context, selection, selectionArgs)
119
+ }
@@ -6,6 +6,7 @@ import android.content.Context
6
6
  import android.media.MediaScannerConnection
7
7
  import android.net.Uri
8
8
  import android.os.Build
9
+ import android.os.Environment
9
10
  import android.provider.MediaStore
10
11
  import androidx.annotation.RequiresApi
11
12
  import expo.modules.core.utilities.ifNull
@@ -17,16 +18,23 @@ import expo.modules.medialibrary.ERROR_IO_EXCEPTION
17
18
  import expo.modules.medialibrary.ERROR_UNABLE_TO_LOAD_PERMISSION
18
19
  import expo.modules.medialibrary.ERROR_UNABLE_TO_SAVE
19
20
  import expo.modules.medialibrary.MediaLibraryUtils
21
+ import expo.modules.medialibrary.albums.getAlbumFileOrNull
20
22
  import java.io.File
21
23
  import java.io.FileInputStream
22
24
  import java.io.FileOutputStream
23
25
  import java.io.IOException
24
26
 
25
- class CreateAsset @JvmOverloads constructor(
27
+ /**
28
+ * Creates an asset entry in the provided albumFile.
29
+ * If no file has been provided the asset will be created in the default directory for the mimeType
30
+ * of the file under the `uri` parameter.
31
+ */
32
+ class CreateAssetWithAlbumFile(
26
33
  private val context: Context,
27
34
  uri: String,
28
35
  private val promise: Promise,
29
- private val resolveWithAdditionalData: Boolean = true
36
+ private val resolveWithAdditionalData: Boolean = true,
37
+ private val albumFile: File?
30
38
  ) {
31
39
  private val mUri = normalizeAssetUri(uri)
32
40
 
@@ -50,7 +58,8 @@ class CreateAsset @JvmOverloads constructor(
50
58
  val contentResolver = context.contentResolver
51
59
  val mimeType = MediaLibraryUtils.getMimeType(contentResolver, mUri)
52
60
  val filename = mUri.lastPathSegment
53
- val path = MediaLibraryUtils.getRelativePathForAssetType(mimeType, true)
61
+ var path = albumFile?.relativeTo(Environment.getExternalStorageDirectory())?.path
62
+ ?: MediaLibraryUtils.getRelativePathForAssetType(mimeType, true)
54
63
 
55
64
  val contentUri = MediaLibraryUtils.mimeTypeToExternalUri(mimeType)
56
65
  val contentValues = ContentValues().apply {
@@ -110,17 +119,14 @@ class CreateAsset @JvmOverloads constructor(
110
119
  * Creates asset using filesystem. Legacy method - do not use above API 29
111
120
  */
112
121
  @Throws(IOException::class)
113
- private fun createAssetFileLegacy(): File {
122
+ private fun createAssetFileLegacy(albumFile: File? = null): File {
114
123
  val localFile = File(mUri.path!!)
115
-
116
- val destDir = MediaLibraryUtils.getEnvDirectoryForAssetType(
117
- MediaLibraryUtils.getMimeType(context.contentResolver, mUri),
118
- true
119
- ).ifNull {
124
+ val mimeType = MediaLibraryUtils.getMimeType(context.contentResolver, mUri).ifNull {
120
125
  throw AssetFileException("Could not guess file type.")
121
126
  }
122
-
127
+ var destDir = albumFile ?: MediaLibraryUtils.getEnvDirectoryForAssetType(mimeType, true)
123
128
  val destFile = MediaLibraryUtils.safeCopyFile(localFile, destDir)
129
+
124
130
  if (!destDir.exists() || !destFile.isFile) {
125
131
  throw AssetFileException("Could not create asset record. Related file does not exist.")
126
132
  }
@@ -137,7 +143,7 @@ class CreateAsset @JvmOverloads constructor(
137
143
  return
138
144
  }
139
145
 
140
- val asset = createAssetFileLegacy()
146
+ val asset = createAssetFileLegacy(albumFile)
141
147
  MediaScannerConnection.scanFile(
142
148
  context,
143
149
  arrayOf(asset.path),
@@ -167,3 +173,20 @@ class CreateAsset @JvmOverloads constructor(
167
173
  }
168
174
  }
169
175
  }
176
+
177
+ class CreateAssetWithAlbumId @JvmOverloads constructor(
178
+ private val context: Context,
179
+ private val uri: String,
180
+ private val promise: Promise,
181
+ private val resolveWithAdditionalData: Boolean = true,
182
+ private val albumId: String? = null
183
+ ) {
184
+ private val album: File?
185
+ get() {
186
+ return albumId?.let { getAlbumFileOrNull(context, albumId) }
187
+ }
188
+
189
+ fun execute() {
190
+ CreateAssetWithAlbumFile(context, uri, promise, resolveWithAdditionalData, album).execute()
191
+ }
192
+ }
@@ -342,9 +342,12 @@ export declare function presentPermissionsPickerAsync(mediaTypes?: MediaTypeFilt
342
342
  * ```
343
343
  * @param localUri A URI to the image or video file. It must contain an extension. On Android it
344
344
  * must be a local path, so it must start with `file:///`
345
+ *
346
+ * @param album An [Album](#album) or its ID. If provided, the asset will be added to this album upon creation, otherwise it will be added to the default album for the media type.
347
+ * The album has exist.
345
348
  * @return A promise which fulfils with an object representing an [`Asset`](#asset).
346
349
  */
347
- export declare function createAssetAsync(localUri: string): Promise<Asset>;
350
+ export declare function createAssetAsync(localUri: string, album?: AlbumRef): Promise<Asset>;
348
351
  /**
349
352
  * Saves the file at given `localUri` to the user's media library. Unlike [`createAssetAsync()`](#medialibrarycreateassetasynclocaluri),
350
353
  * This method doesn't return created asset.
@@ -1 +1 @@
1
- {"version":3,"file":"MediaLibrary.d.ts","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,IAAI,oBAAoB,EAC1C,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EAGrB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAiB3B,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,GAAG;IACtD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;CAC/C,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE7D,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC;AAErF;;;KAGK;AACL,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,WAAW,GACX,OAAO,GACP,QAAQ,GACR,cAAc,GACd,kBAAkB,GAClB,UAAU,CAAC;AACf,MAAM,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;AAE3D,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,QAAQ,CAAC;IACjB,YAAY,EAAE,cAAc,CAAC;IAC7B,gBAAgB,EAAE,kBAAkB,CAAC;IACrC,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,KAAK,GAAG;IAClB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,SAAS,EAAE,cAAc,CAAC;IAC1B;;;OAGG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF;;;KAGK;AACL,MAAM,MAAM,YAAY,GACpB,aAAa,GACb,KAAK,GACL,eAAe,GACf,WAAW,GACX,UAAU,GACV,YAAY,GACZ,QAAQ,GACR,WAAW,CAAC;AAGhB,MAAM,MAAM,iCAAiC,GAAG;IAC9C;;;OAGG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC,CAAC;AAGF,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;;;;;OAMG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IACxB;;;;OAIG;IACH,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;CACzB,CAAC;AAGF,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAGF,MAAM,MAAM,KAAK,GAAG;IAClB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,QAAQ,CAAC;IAC/B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAGF,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAC;AAG1D,MAAM,MAAM,aAAa,GAAG;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAGF,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,GAAG,cAAc,CAAC;IAC9C;;;OAGG;IACH,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC7B;;;OAGG;IACH,aAAa,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC/B,CAAC;AAGF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB;;OAEG;IACH,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAGF,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAGtC,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,IAAI,YAAY,GAClC,CAAC;AAgEF;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,eAAwC,CAAC;AAGjE;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,YAAkC,CAAC;AAGxD;;;;GAIG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEzD;AAGD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,GAAE,OAAe,EAC1B,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,GACzC,OAAO,CAAC,kBAAkB,CAAC,CAQ7B;AAGD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,GAAE,OAAe,EAC1B,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,GACzC,OAAO,CAAC,kBAAkB,CAAC,CAQ7B;AAGD;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;oHAQzB,CAAC;AAGH;;;;;;;;;;;;;GAaG;AACH,wBAAsB,6BAA6B,CACjD,UAAU,GAAE,eAAe,EAAuB,GACjD,OAAO,CAAC,IAAI,CAAC,CAef;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAevE;AAGD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxE;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAC7B,KAAK,EAAE,QAAQ,EACf,IAAI,GAAE,OAAc,GACnB,OAAO,CAAC,OAAO,CAAC,CAkBlB;AAGD;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAC7B,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,OAAO,CAAC,CAUlB;AAGD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CASvF;AAGD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,QAAQ,EACf,OAAO,GAAE,iCAAuE,GAC/E,OAAO,CAAC,SAAS,CAAC,CAgBpB;AAGD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,EAAE,kBAA0B,EAAE,GAAE,aAAkB,GAAG,OAAO,CAC/F,KAAK,EAAE,CACR,CAKA;AAGD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAQjE;AAGD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,QAAQ,EAChB,SAAS,GAAE,OAAc,GACxB,OAAO,CAAC,KAAK,CAAC,CAsBhB;AAGD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAC7B,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC,OAAO,CAAC,CAYlB;AAGD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,aAAa,GAAE,aAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAwCjG;AAGD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,IAAI,GACvD,iBAAiB,CAEnB;AAGD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAExE;AAGD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAGD;;;;;GAKG;AACH,wBAAsB,eAAe,iBAMpC;AAGD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9E;AAGD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAMhF"}
1
+ {"version":3,"file":"MediaLibrary.d.ts","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"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"}
@@ -168,16 +168,20 @@ export async function presentPermissionsPickerAsync(mediaTypes = ['photo', 'vide
168
168
  * ```
169
169
  * @param localUri A URI to the image or video file. It must contain an extension. On Android it
170
170
  * must be a local path, so it must start with `file:///`
171
+ *
172
+ * @param album An [Album](#album) or its ID. If provided, the asset will be added to this album upon creation, otherwise it will be added to the default album for the media type.
173
+ * The album has exist.
171
174
  * @return A promise which fulfils with an object representing an [`Asset`](#asset).
172
175
  */
173
- export async function createAssetAsync(localUri) {
176
+ export async function createAssetAsync(localUri, album) {
174
177
  if (!MediaLibrary.createAssetAsync) {
175
178
  throw new UnavailabilityError('MediaLibrary', 'createAssetAsync');
176
179
  }
180
+ const albumId = getId(album);
177
181
  if (!localUri || typeof localUri !== 'string') {
178
182
  throw new Error('Invalid argument "localUri". It must be a string!');
179
183
  }
180
- const asset = await MediaLibrary.createAssetAsync(localUri);
184
+ const asset = await MediaLibrary.createAssetAsync(localUri, albumId);
181
185
  if (Array.isArray(asset)) {
182
186
  // Android returns an array with asset, we need to pick the first item
183
187
  return asset[0];
@@ -1 +1 @@
1
- {"version":3,"file":"MediaLibrary.js","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAGhB,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAE9C,MAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,WAAW,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC;AAEjF,IAAI,mBAAmB,GAAG,KAAK,CAAC;AAEhC,IAAI,QAAQ,IAAI,CAAC,mBAAmB,EAAE;IACpC,OAAO,CAAC,IAAI,CACV,wQAAwQ,CACzQ,CAAC;IACF,mBAAmB,GAAG,IAAI,CAAC;CAC5B;AAmUD,OAAO,EACL,gBAAgB,GAKjB,CAAC;AAEF,SAAS,QAAQ,CAAC,IAAS;IACzB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IACD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,KAAK,CAAC,GAAQ;IACrB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,OAAO,GAAG,CAAC;KACZ;IACD,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAClC,CAAC;AAED,SAAS,aAAa,CAAC,QAAa;IAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE;QACxD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;AACH,CAAC;AAED,SAAS,aAAa,CAAC,QAAa;IAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE;QACxD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;AACH,CAAC;AAED,SAAS,cAAc,CAAC,SAAc;IACpC,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;KACpD;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAW;IAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;SAClF;KACF;SAAM;QACL,cAAc,CAAC,MAAM,CAAC,CAAC;KACxB;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAW;IACjC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;QAChD,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;KAClD;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAW;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KACrD;IACD,OAAO,GAAG,MAAM,OAAO,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,KAAqB;IACzC,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC;AAED,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAoB,YAAY,CAAC,SAAS,CAAC;AAEjE,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAiB,YAAY,CAAC,MAAM,CAAC;AAExD,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,CAAC,CAAC,YAAY,IAAI,gBAAgB,IAAI,YAAY,CAAC;AAC5D,CAAC;AAED,2BAA2B;AAC3B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,YAAqB,KAAK,EAC1B,mBAA0C;IAE1C,IAAI,CAAC,YAAY,CAAC,uBAAuB,EAAE;QACzC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;KAC1E;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,YAAY,CAAC,uBAAuB,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;KACnF;IACD,OAAO,MAAM,YAAY,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED,2BAA2B;AAC3B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAqB,KAAK,EAC1B,mBAA0C;IAE1C,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE;QACrC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;KACtE;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,YAAY,CAAC,mBAAmB,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;KAC/E;IACD,OAAO,MAAM,YAAY,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;AAC3D,CAAC;AAED,cAAc;AACd;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAGhD;IACA,4FAA4F;IAC5F,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,CAAC;IAC7F,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CACzB,uBAAuB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,CAAC;CAC5E,CAAC,CAAC;AAEH,cAAc;AACd;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,aAAgC,CAAC,OAAO,EAAE,OAAO,CAAC;IAElD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,EAAE;QACzC,MAAM,IAAI,mBAAmB,CAC3B,cAAc,EACd,yDAAyD,CAC1D,CAAC;KACH;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE;QACvD,MAAM,YAAY,CAAC,uBAAuB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC9D,OAAO;KACR;IACD,IAAI,CAAC,YAAY,CAAC,6BAA6B,EAAE;QAC/C,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,+BAA+B,CAAC,CAAC;KAChF;IACD,OAAO,MAAM,YAAY,CAAC,6BAA6B,EAAE,CAAC;AAC5D,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE;QAClC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;KACnE;IAED,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;QAC7C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;KACtE;IACD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE5D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACxB,sEAAsE;QACtE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;KACjB;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE;QACpC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;KACrE;IACD,OAAO,MAAM,YAAY,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAA6B,EAC7B,KAAe,EACf,OAAgB,IAAI;IAEpB,IAAI,CAAC,YAAY,CAAC,qBAAqB,EAAE;QACvC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,uBAAuB,CAAC,CAAC;KACxE;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,aAAa,CAAC,QAAQ,CAAC,CAAC;IAExB,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC3C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;KAC3D;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,OAAO,MAAM,YAAY,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;KACpE;IACD,OAAO,MAAM,YAAY,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,cAAc;AACd;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAA6B,EAC7B,KAAe;IAEf,IAAI,CAAC,YAAY,CAAC,0BAA0B,EAAE;QAC5C,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,4BAA4B,CAAC,CAAC;KAC7E;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,MAAM,YAAY,CAAC,0BAA0B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED,cAAc;AACd;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAA6B;IACnE,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;KACpE;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE7C,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,MAAM,YAAY,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AACxD,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAe,EACf,UAA6C,EAAE,yBAAyB,EAAE,IAAI,EAAE;IAEhF,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;KACpE;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEzE,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QAC5B,2EAA2E;QAC3E,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;KACrB;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAE,kBAAkB,GAAG,KAAK,KAAoB,EAAE;IAGrF,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE;QAChC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;KACjE;IACD,OAAO,MAAM,YAAY,CAAC,cAAc,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE;QAC/B,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;KAChE;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;KAClD;IACD,OAAO,MAAM,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,cAAc;AACd;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,KAAgB,EAChB,YAAqB,IAAI;IAEzB,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE;QAClC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;KACnE;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE;QACtF,wFAAwF;QACxF,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;KAC3F;IACD,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE;QAC/C,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;KACvE;IACD,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAClD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,OAAO,MAAM,YAAY,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;KAChE;IACD,OAAO,MAAM,YAAY,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAC9E,CAAC;AAED,cAAc;AACd;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAA6B,EAC7B,cAAuB,KAAK;IAE5B,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;KACpE;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE7C,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,YAAY,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;KACvD;IACD,OAAO,MAAM,YAAY,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;AACvE,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,gBAA+B,EAAE;IACpE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE;QAChC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;KACjE;IAED,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC;IAE9F,MAAM,OAAO,GAAG;QACd,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK;QACjC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;QACxB,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnD,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC;QACxC,aAAa,EAAE,YAAY,CAAC,aAAa,CAAC;KAC3C,CAAC;IAEF,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IACD,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IACD,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IAED,IAAI,KAAK,IAAI,IAAI,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAW,EAAE,EAAE,CAAC,CAAC,EAAE;QAC7F,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;KACvD;IAED,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE;QAC9B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;KAC/D;IAED,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACpC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAE1D,OAAO,MAAM,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACpD,CAAC;AAED,cAAc;AACd;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,QAAwD;IAExD,OAAO,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,eAAe;AACf,MAAM,UAAU,kBAAkB,CAAC,YAA+B;IAChE,YAAY,CAAC,MAAM,EAAE,CAAC;AACxB,CAAC;AAED,cAAc;AACd;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,YAAY,CAAC,kBAAkB,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC;AACrE,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE;QACjC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;KAClE;IAED,OAAO,MAAM,YAAY,CAAC,eAAe,EAAE,CAAC;AAC9C,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAAe;IAC7D,IAAI,CAAC,YAAY,CAAC,yBAAyB,EAAE;QAC3C,OAAO;KACR;IAED,OAAO,MAAM,YAAY,CAAC,yBAAyB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,cAAc;AACd;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAAe;IAC5D,IAAI,CAAC,YAAY,CAAC,wBAAwB,EAAE;QAC1C,OAAO,KAAK,CAAC;KACd;IAED,OAAO,MAAM,YAAY,CAAC,wBAAwB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC","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"]}
1
+ {"version":3,"file":"MediaLibrary.js","sourceRoot":"","sources":["../src/MediaLibrary.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAGhB,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAE9C,MAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,WAAW,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC;AAEjF,IAAI,mBAAmB,GAAG,KAAK,CAAC;AAEhC,IAAI,QAAQ,IAAI,CAAC,mBAAmB,EAAE;IACpC,OAAO,CAAC,IAAI,CACV,wQAAwQ,CACzQ,CAAC;IACF,mBAAmB,GAAG,IAAI,CAAC;CAC5B;AAmUD,OAAO,EACL,gBAAgB,GAKjB,CAAC;AAEF,SAAS,QAAQ,CAAC,IAAS;IACzB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IACD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,KAAK,CAAC,GAAQ;IACrB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,OAAO,GAAG,CAAC;KACZ;IACD,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAClC,CAAC;AAED,SAAS,aAAa,CAAC,QAAa;IAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE;QACxD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;AACH,CAAC;AAED,SAAS,aAAa,CAAC,QAAa;IAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,EAAE;QACxD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;AACH,CAAC;AAED,SAAS,cAAc,CAAC,SAAc;IACpC,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;KACpD;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAW;IAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE;YAClC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;SAClF;KACF;SAAM;QACL,cAAc,CAAC,MAAM,CAAC,CAAC;KACxB;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAW;IACjC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;QAChD,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;KAClD;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAW;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KACrD;IACD,OAAO,GAAG,MAAM,OAAO,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,KAAqB;IACzC,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC;AAED,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAoB,YAAY,CAAC,SAAS,CAAC;AAEjE,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAiB,YAAY,CAAC,MAAM,CAAC;AAExD,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,CAAC,CAAC,YAAY,IAAI,gBAAgB,IAAI,YAAY,CAAC;AAC5D,CAAC;AAED,2BAA2B;AAC3B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,YAAqB,KAAK,EAC1B,mBAA0C;IAE1C,IAAI,CAAC,YAAY,CAAC,uBAAuB,EAAE;QACzC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;KAC1E;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,YAAY,CAAC,uBAAuB,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;KACnF;IACD,OAAO,MAAM,YAAY,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED,2BAA2B;AAC3B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAqB,KAAK,EAC1B,mBAA0C;IAE1C,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE;QACrC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;KACtE;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,YAAY,CAAC,mBAAmB,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;KAC/E;IACD,OAAO,MAAM,YAAY,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;AAC3D,CAAC;AAED,cAAc;AACd;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAGhD;IACA,4FAA4F;IAC5F,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,CAAC;IAC7F,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CACzB,uBAAuB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,CAAC;CAC5E,CAAC,CAAC;AAEH,cAAc;AACd;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,aAAgC,CAAC,OAAO,EAAE,OAAO,CAAC;IAElD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,EAAE;QACzC,MAAM,IAAI,mBAAmB,CAC3B,cAAc,EACd,yDAAyD,CAC1D,CAAC;KACH;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE;QACvD,MAAM,YAAY,CAAC,uBAAuB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC9D,OAAO;KACR;IACD,IAAI,CAAC,YAAY,CAAC,6BAA6B,EAAE;QAC/C,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,+BAA+B,CAAC,CAAC;KAChF;IACD,OAAO,MAAM,YAAY,CAAC,6BAA6B,EAAE,CAAC;AAC5D,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,KAAgB;IACvE,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE;QAClC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;KACnE;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;QAC7C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;KACtE;IACD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAErE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACxB,sEAAsE;QACtE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;KACjB;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE;QACpC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;KACrE;IACD,OAAO,MAAM,YAAY,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACzD,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAA6B,EAC7B,KAAe,EACf,OAAgB,IAAI;IAEpB,IAAI,CAAC,YAAY,CAAC,qBAAqB,EAAE;QACvC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,uBAAuB,CAAC,CAAC;KACxE;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,aAAa,CAAC,QAAQ,CAAC,CAAC;IAExB,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC3C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;KAC3D;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,OAAO,MAAM,YAAY,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;KACpE;IACD,OAAO,MAAM,YAAY,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,cAAc;AACd;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAA6B,EAC7B,KAAe;IAEf,IAAI,CAAC,YAAY,CAAC,0BAA0B,EAAE;QAC5C,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,4BAA4B,CAAC,CAAC;KAC7E;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,MAAM,YAAY,CAAC,0BAA0B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED,cAAc;AACd;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAA6B;IACnE,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;KACpE;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE7C,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,MAAM,YAAY,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AACxD,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAe,EACf,UAA6C,EAAE,yBAAyB,EAAE,IAAI,EAAE;IAEhF,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;KACpE;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEzE,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QAC5B,2EAA2E;QAC3E,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;KACrB;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAE,kBAAkB,GAAG,KAAK,KAAoB,EAAE;IAGrF,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE;QAChC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;KACjE;IACD,OAAO,MAAM,YAAY,CAAC,cAAc,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE;QAC/B,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;KAChE;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;KAClD;IACD,OAAO,MAAM,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,cAAc;AACd;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,KAAgB,EAChB,YAAqB,IAAI;IAEzB,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE;QAClC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;KACnE;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE;QACtF,wFAAwF;QACxF,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;KAC3F;IACD,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE;QAC/C,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;KACvE;IACD,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAClD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,OAAO,MAAM,YAAY,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;KAChE;IACD,OAAO,MAAM,YAAY,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAC9E,CAAC;AAED,cAAc;AACd;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAA6B,EAC7B,cAAuB,KAAK;IAE5B,IAAI,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;KACpE;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE7C,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QAC7B,OAAO,MAAM,YAAY,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;KACvD;IACD,OAAO,MAAM,YAAY,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;AACvE,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,gBAA+B,EAAE;IACpE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE;QAChC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;KACjE;IAED,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC;IAE9F,MAAM,OAAO,GAAG;QACd,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK;QACjC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;QACnB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;QACxB,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnD,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC;QACxC,aAAa,EAAE,YAAY,CAAC,aAAa,CAAC;KAC3C,CAAC;IAEF,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IACD,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IACD,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IAED,IAAI,KAAK,IAAI,IAAI,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAW,EAAE,EAAE,CAAC,CAAC,EAAE;QAC7F,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;KACvD;IAED,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE;QAC9B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;KAC/D;IAED,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACpC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAE1D,OAAO,MAAM,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACpD,CAAC;AAED,cAAc;AACd;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,QAAwD;IAExD,OAAO,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,eAAe;AACf,MAAM,UAAU,kBAAkB,CAAC,YAA+B;IAChE,YAAY,CAAC,MAAM,EAAE,CAAC;AACxB,CAAC;AAED,cAAc;AACd;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,YAAY,CAAC,kBAAkB,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC;AACrE,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE;QACjC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;KAClE;IAED,OAAO,MAAM,YAAY,CAAC,eAAe,EAAE,CAAC;AAC9C,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAAe;IAC7D,IAAI,CAAC,YAAY,CAAC,yBAAyB,EAAE;QAC3C,OAAO;KACR;IAED,OAAO,MAAM,YAAY,CAAC,yBAAyB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,cAAc;AACd;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAAe;IAC5D,IAAI,CAAC,YAAY,CAAC,wBAAwB,EAAE;QAC1C,OAAO,KAAK,CAAC;KACd;IAED,OAAO,MAAM,YAAY,CAAC,wBAAwB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC","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 *\n * @param album An [Album](#album) or its ID. If provided, the asset will be added to this album upon creation, otherwise it will be added to the default album for the media type.\n * The album has exist.\n * @return A promise which fulfils with an object representing an [`Asset`](#asset).\n */\nexport async function createAssetAsync(localUri: string, album?: AlbumRef): Promise<Asset> {\n if (!MediaLibrary.createAssetAsync) {\n throw new UnavailabilityError('MediaLibrary', 'createAssetAsync');\n }\n\n const albumId = getId(album);\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, albumId);\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"]}
@@ -4,6 +4,12 @@
4
4
  "modules": ["MediaLibraryModule"]
5
5
  },
6
6
  "android": {
7
- "modules": ["expo.modules.medialibrary.MediaLibraryModule"]
7
+ "modules": ["expo.modules.medialibrary.MediaLibraryModule"],
8
+ "publication": {
9
+ "groupId": "host.exp.exponent",
10
+ "artifactId": "expo.modules.medialibrary",
11
+ "version": "17.1.0-canary-20250402-161f57b",
12
+ "repository": "https://maven.pkg.github.com/expo/expo"
13
+ }
8
14
  }
9
15
  }
@@ -73,40 +73,28 @@ public class MediaLibraryModule: Module, PhotoLibraryObserverHandler {
73
73
  #endif
74
74
  }.runOnQueue(.main)
75
75
 
76
- AsyncFunction("createAssetAsync") { (uri: URL, promise: Promise) in
76
+ AsyncFunction("createAssetAsync") { (uri: URL, albumId: String?, promise: Promise) in
77
77
  if !checkPermissions(promise: promise) {
78
78
  return
79
79
  }
80
80
 
81
- if uri.pathExtension.isEmpty {
82
- promise.reject(EmptyFileExtensionException())
83
- return
84
- }
85
-
86
- let assetType = assetType(for: uri)
87
- if assetType == .unknown || assetType == .audio {
88
- promise.reject(UnsupportedAssetTypeException(uri.absoluteString))
89
- return
90
- }
91
-
92
- if !FileSystemUtilities.permissions(appContext, for: uri).contains(.read) {
93
- promise.reject(UnreadableAssetException(uri.absoluteString))
94
- return
95
- }
96
-
97
- var assetPlaceholder: PHObjectPlaceholder?
98
- PHPhotoLibrary.shared().performChanges {
99
- let changeRequest = assetType == .video
100
- ? PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: uri)
101
- : PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: uri)
81
+ createAsset(uri: uri, appContext: appContext) { asset, error in
82
+ guard let asset else {
83
+ promise.reject(error ?? SaveAssetException(nil))
84
+ return
85
+ }
102
86
 
103
- assetPlaceholder = changeRequest?.placeholderForCreatedAsset
104
- } completionHandler: { success, error in
105
- if success {
106
- let asset = getAssetBy(id: assetPlaceholder?.localIdentifier)
87
+ guard let albumId else {
107
88
  promise.resolve(exportAsset(asset: asset))
108
- } else {
109
- promise.reject(SaveAssetException(error))
89
+ return
90
+ }
91
+
92
+ addAssets(ids: [asset.localIdentifier], to: albumId) { success, error in
93
+ if success {
94
+ promise.resolve(exportAsset(asset: asset))
95
+ } else {
96
+ promise.reject(error ?? SaveAssetException(nil))
97
+ }
110
98
  }
111
99
  }
112
100
  }
@@ -264,6 +264,41 @@ func createAlbum(with title: String, completion: @escaping (PHAssetCollection?,
264
264
  }
265
265
  }
266
266
 
267
+ func createAsset(uri: URL, appContext: AppContext?, completion: @escaping (PHAsset?, Error?) -> Void) {
268
+ let assetType = assetType(for: uri)
269
+
270
+ if uri.pathExtension.isEmpty {
271
+ completion(nil, EmptyFileExtensionException())
272
+ return
273
+ }
274
+
275
+ if assetType == .unknown || assetType == .audio {
276
+ completion(nil, UnsupportedAssetTypeException(uri.absoluteString))
277
+ return
278
+ }
279
+
280
+ if !FileSystemUtilities.permissions(appContext, for: uri).contains(.read) {
281
+ completion(nil, UnreadableAssetException(uri.absoluteString))
282
+ return
283
+ }
284
+
285
+ var assetPlaceholder: PHObjectPlaceholder?
286
+ PHPhotoLibrary.shared().performChanges {
287
+ let changeRequest = assetType == .video
288
+ ? PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: uri)
289
+ : PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: uri)
290
+
291
+ assetPlaceholder = changeRequest?.placeholderForCreatedAsset
292
+ } completionHandler: { success, error in
293
+ if success {
294
+ let asset = getAssetBy(id: assetPlaceholder?.localIdentifier)
295
+ completion(asset, nil)
296
+ } else {
297
+ completion(nil, SaveAssetException(error))
298
+ }
299
+ }
300
+ }
301
+
267
302
  func assetType(for localUri: URL) -> PHAssetMediaType {
268
303
  guard let type = UTType(filenameExtension: localUri.pathExtension) else {
269
304
  return assetTypeExtension(for: localUri.pathExtension)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-media-library",
3
- "version": "17.1.0-canary-20250320-7a205d3",
3
+ "version": "17.1.0-canary-20250402-161f57b",
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.5-canary-20250320-7a205d3"
41
+ "expo-module-scripts": "4.0.5-canary-20250402-161f57b"
42
42
  },
43
43
  "peerDependencies": {
44
- "expo": "53.0.0-canary-20250320-7a205d3",
44
+ "expo": "53.0.0-canary-20250402-161f57b",
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": "161f57bb5f579c84f8fa0337ec596034e21760f6"
57
58
  }
@@ -542,17 +542,22 @@ export async function presentPermissionsPickerAsync(
542
542
  * ```
543
543
  * @param localUri A URI to the image or video file. It must contain an extension. On Android it
544
544
  * must be a local path, so it must start with `file:///`
545
+ *
546
+ * @param album An [Album](#album) or its ID. If provided, the asset will be added to this album upon creation, otherwise it will be added to the default album for the media type.
547
+ * The album has exist.
545
548
  * @return A promise which fulfils with an object representing an [`Asset`](#asset).
546
549
  */
547
- export async function createAssetAsync(localUri: string): Promise<Asset> {
550
+ export async function createAssetAsync(localUri: string, album?: AlbumRef): Promise<Asset> {
548
551
  if (!MediaLibrary.createAssetAsync) {
549
552
  throw new UnavailabilityError('MediaLibrary', 'createAssetAsync');
550
553
  }
551
554
 
555
+ const albumId = getId(album);
556
+
552
557
  if (!localUri || typeof localUri !== 'string') {
553
558
  throw new Error('Invalid argument "localUri". It must be a string!');
554
559
  }
555
- const asset = await MediaLibrary.createAssetAsync(localUri);
560
+ const asset = await MediaLibrary.createAssetAsync(localUri, albumId);
556
561
 
557
562
  if (Array.isArray(asset)) {
558
563
  // Android returns an array with asset, we need to pick the first item