expo-media-library 18.3.0-canary-20251120-e46b3cc → 18.3.0-canary-20251205-756eb7a
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 +7 -0
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/expo/modules/medialibrary/next/MediaLibraryNextModule.kt +8 -0
- package/android/src/main/java/expo/modules/medialibrary/next/extensions/resolver/AssetExtensions.kt +31 -11
- package/android/src/main/java/expo/modules/medialibrary/next/extensions/resolver/AssetMediaStoreItem.kt +100 -0
- package/android/src/main/java/expo/modules/medialibrary/next/objects/asset/Asset.kt +8 -0
- package/android/src/main/java/expo/modules/medialibrary/next/objects/asset/delegates/AssetDelegate.kt +4 -0
- package/android/src/main/java/expo/modules/medialibrary/next/objects/asset/delegates/AssetLegacyDelegate.kt +61 -48
- package/android/src/main/java/expo/modules/medialibrary/next/objects/asset/delegates/AssetModernDelegate.kt +56 -42
- package/android/src/main/java/expo/modules/medialibrary/next/objects/asset/delegates/MediaStoreToAssetAdapter.kt +75 -0
- package/android/src/main/java/expo/modules/medialibrary/next/objects/asset/deleters/AssetLegacyDeleter.kt +2 -2
- package/android/src/main/java/expo/modules/medialibrary/next/records/AssetInfo.kt +18 -0
- package/android/src/main/java/expo/modules/medialibrary/next/records/Shape.kt +9 -0
- package/build/next/ExpoMediaLibraryNext.d.ts +8 -1
- package/build/next/ExpoMediaLibraryNext.d.ts.map +1 -1
- package/build/next/ExpoMediaLibraryNext.js.map +1 -1
- package/build/next/MediaLibraryNext.types.d.ts +1 -0
- package/build/next/MediaLibraryNext.types.d.ts.map +1 -1
- package/build/next/MediaLibraryNext.types.js +1 -0
- package/build/next/MediaLibraryNext.types.js.map +1 -1
- package/build/next/types/Asset.d.ts +14 -0
- package/build/next/types/Asset.d.ts.map +1 -1
- package/build/next/types/Asset.js.map +1 -1
- package/build/next/types/AssetInfo.d.ts +13 -0
- package/build/next/types/AssetInfo.d.ts.map +1 -0
- package/build/next/types/AssetInfo.js +2 -0
- package/build/next/types/AssetInfo.js.map +1 -0
- package/build/next/types/Shape.d.ts +5 -0
- package/build/next/types/Shape.d.ts.map +1 -0
- package/build/next/types/Shape.js +2 -0
- package/build/next/types/Shape.js.map +1 -0
- package/expo-module.config.json +1 -1
- package/ios/next/MediaLibraryNextModule.swift +8 -0
- package/ios/next/objects/asset/Asset.swift +22 -0
- package/ios/next/objects/asset/AssetInfo.swift +37 -0
- package/ios/next/objects/asset/Shape.swift +13 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/{18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc-sources.jar → 18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a-sources.jar} +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a-sources.jar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a-sources.jar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a-sources.jar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a-sources.jar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.aar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.aar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.aar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.aar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/{18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.module → 18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.module} +22 -22
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.module.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.module.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.module.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.module.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/{18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.pom → 18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.pom} +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.pom.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.pom.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.pom.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251205-756eb7a/expo.modules.medialibrary-18.3.0-canary-20251205-756eb7a.pom.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/maven-metadata.xml +4 -4
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/maven-metadata.xml.sha512 +1 -1
- package/package.json +3 -3
- package/src/next/ExpoMediaLibraryNext.ts +14 -1
- package/src/next/MediaLibraryNext.types.ts +1 -0
- package/src/next/types/Asset.ts +16 -0
- package/src/next/types/AssetInfo.ts +13 -0
- package/src/next/types/Shape.ts +4 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc-sources.jar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc-sources.jar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc-sources.jar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc-sources.jar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.aar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.aar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.aar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.aar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.module.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.module.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.module.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.module.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.pom.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.pom.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.pom.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.medialibrary/18.3.0-canary-20251120-e46b3cc/expo.modules.medialibrary-18.3.0-canary-20251120-e46b3cc.pom.sha512 +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
### 🎉 New features
|
|
8
8
|
|
|
9
|
+
- [next] Add `asset.getShape()` ([#40110](https://github.com/expo/expo/pull/40110) by [@Wenszel](https://github.com/Wenszel))
|
|
10
|
+
- [next] Add `asset.getInfo()` ([#40146](https://github.com/expo/expo/pull/40146) by [@Wenszel](https://github.com/Wenszel))
|
|
9
11
|
- [next] Add exif support ([#39992](https://github.com/expo/expo/pull/39992) by [@Wenszel](https://github.com/Wenszel))
|
|
10
12
|
- [next] Add `Album.get(title)` ([#39717](https://github.com/expo/expo/pull/39717) by [@Wenszel](https://github.com/Wenszel))
|
|
11
13
|
|
|
@@ -23,6 +25,11 @@
|
|
|
23
25
|
- [next] Add test screens ([#39951](https://github.com/expo/expo/pull/39951) by [@Wenszel](https://github.com/Wenszel))
|
|
24
26
|
- [next] Add documentation ([#39754](https://github.com/expo/expo/pull/39754) by [@Wenszel](https://github.com/Wenszel))
|
|
25
27
|
- Remove tests related files from the published package content. ([#39551](https://github.com/expo/expo/pull/39551) by [@Simek](https://github.com/Simek))
|
|
28
|
+
- [Android] Add `android:maxSdkVersion` annotation to `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` permissions. ([#40976](https://github.com/expo/expo/pull/40976) by [@behenate](https://github.com/behenate))
|
|
29
|
+
|
|
30
|
+
## 18.2.1 - 2025-12-05
|
|
31
|
+
|
|
32
|
+
_This version does not introduce any user-facing changes._
|
|
26
33
|
|
|
27
34
|
## 18.2.0 — 2025-09-16
|
|
28
35
|
|
package/android/build.gradle
CHANGED
|
@@ -4,13 +4,13 @@ plugins {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
group = 'host.exp.exponent'
|
|
7
|
-
version = '18.3.0-canary-
|
|
7
|
+
version = '18.3.0-canary-20251205-756eb7a'
|
|
8
8
|
|
|
9
9
|
android {
|
|
10
10
|
namespace "expo.modules.medialibrary"
|
|
11
11
|
defaultConfig {
|
|
12
12
|
versionCode 37
|
|
13
|
-
versionName "18.3.0-canary-
|
|
13
|
+
versionName "18.3.0-canary-20251205-756eb7a"
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
2
|
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
|
3
|
-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
4
|
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
3
|
+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
|
4
|
+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
|
5
5
|
</manifest>
|
|
@@ -93,6 +93,10 @@ class MediaLibraryNextModule : Module() {
|
|
|
93
93
|
self.getExif()
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
AsyncFunction("getInfo") Coroutine { self: Asset ->
|
|
97
|
+
self.getInfo()
|
|
98
|
+
}
|
|
99
|
+
|
|
96
100
|
AsyncFunction("getLocation") Coroutine { self: Asset ->
|
|
97
101
|
self.getLocation()
|
|
98
102
|
}
|
|
@@ -113,6 +117,10 @@ class MediaLibraryNextModule : Module() {
|
|
|
113
117
|
self.getModificationTime()
|
|
114
118
|
}
|
|
115
119
|
|
|
120
|
+
AsyncFunction("getShape") Coroutine { self: Asset ->
|
|
121
|
+
self.getShape()
|
|
122
|
+
}
|
|
123
|
+
|
|
116
124
|
AsyncFunction("getUri") Coroutine { self: Asset ->
|
|
117
125
|
self.getUri()
|
|
118
126
|
}
|
package/android/src/main/java/expo/modules/medialibrary/next/extensions/resolver/AssetExtensions.kt
CHANGED
|
@@ -9,34 +9,54 @@ import android.provider.MediaStore
|
|
|
9
9
|
import androidx.annotation.RequiresApi
|
|
10
10
|
import expo.modules.medialibrary.EXTERNAL_CONTENT_URI
|
|
11
11
|
import expo.modules.medialibrary.next.exceptions.AssetCouldNotBeCreated
|
|
12
|
+
import expo.modules.medialibrary.next.extensions.resolver.AssetMediaStoreItemBuilder.Companion.buildAssetMediaStoreItem
|
|
13
|
+
import expo.modules.medialibrary.next.objects.wrappers.MediaType
|
|
12
14
|
import expo.modules.medialibrary.next.objects.wrappers.RelativePath
|
|
13
15
|
import expo.modules.medialibrary.next.objects.wrappers.MimeType
|
|
14
16
|
import kotlinx.coroutines.Dispatchers
|
|
15
17
|
import kotlinx.coroutines.withContext
|
|
16
18
|
|
|
17
19
|
suspend fun ContentResolver.queryAssetDisplayName(contentUri: Uri): String? =
|
|
18
|
-
queryOne(contentUri,
|
|
20
|
+
queryOne(contentUri, AssetMediaStoreProperty.DisplayName.column, Cursor::getString)
|
|
19
21
|
|
|
20
|
-
suspend fun ContentResolver.
|
|
21
|
-
queryOne(contentUri,
|
|
22
|
+
suspend fun ContentResolver.queryAssetDateTaken(contentUri: Uri): Long? =
|
|
23
|
+
queryOne(contentUri, AssetMediaStoreProperty.DateTaken.column, Cursor::getLong)
|
|
22
24
|
|
|
23
|
-
suspend fun ContentResolver.
|
|
24
|
-
queryOne(contentUri,
|
|
25
|
+
suspend fun ContentResolver.queryAssetDateModified(contentUri: Uri): Long? =
|
|
26
|
+
queryOne(contentUri, AssetMediaStoreProperty.DateModified.column, Cursor::getLong)
|
|
25
27
|
|
|
26
28
|
suspend fun ContentResolver.queryAssetDuration(contentUri: Uri): Long? =
|
|
27
|
-
queryOne(contentUri,
|
|
29
|
+
queryOne(contentUri, AssetMediaStoreProperty.Duration.column, Cursor::getLong)
|
|
28
30
|
|
|
29
31
|
suspend fun ContentResolver.queryAssetWidth(contentUri: Uri): Int? =
|
|
30
|
-
queryOne(contentUri,
|
|
32
|
+
queryOne(contentUri, AssetMediaStoreProperty.Width.column, Cursor::getInt)
|
|
31
33
|
|
|
32
34
|
suspend fun ContentResolver.queryAssetHeight(contentUri: Uri): Int? =
|
|
33
|
-
queryOne(contentUri,
|
|
35
|
+
queryOne(contentUri, AssetMediaStoreProperty.Height.column, Cursor::getInt)
|
|
34
36
|
|
|
35
|
-
suspend fun ContentResolver.
|
|
36
|
-
queryOne(contentUri,
|
|
37
|
+
suspend fun ContentResolver.queryAssetData(contentUri: Uri): String? =
|
|
38
|
+
queryOne(contentUri, AssetMediaStoreProperty.Data.column, Cursor::getString)
|
|
37
39
|
|
|
38
40
|
suspend fun ContentResolver.queryAssetBucketId(contentUri: Uri): Int? =
|
|
39
|
-
queryOne(contentUri,
|
|
41
|
+
queryOne(contentUri, AssetMediaStoreProperty.BucketId.column, Cursor::getInt)
|
|
42
|
+
|
|
43
|
+
suspend fun ContentResolver.queryAssetMediaStoreItem(
|
|
44
|
+
contentUri: Uri
|
|
45
|
+
): AssetMediaStoreItem? = withContext(Dispatchers.IO) {
|
|
46
|
+
// Attempting to get a duration from an image may result in an exception on older Android versions
|
|
47
|
+
val includeDuration = MediaType.fromContentUri(contentUri) != MediaType.IMAGE
|
|
48
|
+
val projection = AssetMediaStoreProperty.projection(includeDuration)
|
|
49
|
+
val cursor = safeQuery(contentUri, projection, null, null)
|
|
50
|
+
?: return@withContext null
|
|
51
|
+
|
|
52
|
+
return@withContext cursor.use {
|
|
53
|
+
if (it.moveToFirst()) {
|
|
54
|
+
it.buildAssetMediaStoreItem(includeDuration)
|
|
55
|
+
} else {
|
|
56
|
+
null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
40
60
|
|
|
41
61
|
suspend fun ContentResolver.insertPendingAsset(
|
|
42
62
|
displayName: String,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
package expo.modules.medialibrary.next.extensions.resolver
|
|
2
|
+
|
|
3
|
+
import android.database.Cursor
|
|
4
|
+
import android.provider.MediaStore
|
|
5
|
+
|
|
6
|
+
data class AssetMediaStoreItem(
|
|
7
|
+
val displayName: String?,
|
|
8
|
+
val height: Int?,
|
|
9
|
+
val width: Int?,
|
|
10
|
+
val dateTaken: Long?,
|
|
11
|
+
val dateModified: Long?,
|
|
12
|
+
val duration: Long?,
|
|
13
|
+
val data: String?,
|
|
14
|
+
val bucketId: String?
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
class AssetMediaStoreItemBuilder {
|
|
18
|
+
private var displayName: String? = null
|
|
19
|
+
private var height: Int? = null
|
|
20
|
+
private var width: Int? = null
|
|
21
|
+
private var dateTaken: Long? = null
|
|
22
|
+
private var dateModified: Long? = null
|
|
23
|
+
private var duration: Long? = null
|
|
24
|
+
private var data: String? = null
|
|
25
|
+
private var bucketId: String? = null
|
|
26
|
+
|
|
27
|
+
fun build(): AssetMediaStoreItem {
|
|
28
|
+
return AssetMediaStoreItem(
|
|
29
|
+
displayName = displayName,
|
|
30
|
+
height = height,
|
|
31
|
+
width = width,
|
|
32
|
+
dateTaken = dateTaken,
|
|
33
|
+
dateModified = dateModified,
|
|
34
|
+
duration = duration,
|
|
35
|
+
data = data,
|
|
36
|
+
bucketId = bucketId
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun Cursor.set(property: AssetMediaStoreProperty) {
|
|
41
|
+
with(property) {
|
|
42
|
+
when (property) {
|
|
43
|
+
AssetMediaStoreProperty.Data -> data = getString()
|
|
44
|
+
AssetMediaStoreProperty.DisplayName -> displayName = getString()
|
|
45
|
+
AssetMediaStoreProperty.Height -> height = getInt()
|
|
46
|
+
AssetMediaStoreProperty.Width -> width = getInt()
|
|
47
|
+
AssetMediaStoreProperty.DateTaken -> dateTaken = getLong()
|
|
48
|
+
AssetMediaStoreProperty.DateModified -> dateModified = getLong()
|
|
49
|
+
AssetMediaStoreProperty.Duration -> duration = getLong()
|
|
50
|
+
AssetMediaStoreProperty.BucketId -> bucketId = getString()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
companion object {
|
|
56
|
+
fun Cursor.buildAssetMediaStoreItem(includeDuration: Boolean): AssetMediaStoreItem {
|
|
57
|
+
val assetMediaStoreItemBuilder = AssetMediaStoreItemBuilder()
|
|
58
|
+
AssetMediaStoreProperty
|
|
59
|
+
.values()
|
|
60
|
+
.filter { includeDuration || it != AssetMediaStoreProperty.Duration }
|
|
61
|
+
.forEach {
|
|
62
|
+
with(assetMediaStoreItemBuilder) {
|
|
63
|
+
set(it)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return assetMediaStoreItemBuilder.build()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
enum class AssetMediaStoreProperty(val column: String) {
|
|
72
|
+
DisplayName(MediaStore.Files.FileColumns.DISPLAY_NAME),
|
|
73
|
+
Height(MediaStore.MediaColumns.HEIGHT),
|
|
74
|
+
Width(MediaStore.MediaColumns.WIDTH),
|
|
75
|
+
DateTaken(MediaStore.Images.ImageColumns.DATE_TAKEN),
|
|
76
|
+
DateModified(MediaStore.MediaColumns.DATE_MODIFIED),
|
|
77
|
+
Duration(MediaStore.MediaColumns.DURATION),
|
|
78
|
+
Data(MediaStore.MediaColumns.DATA),
|
|
79
|
+
BucketId(MediaStore.MediaColumns.BUCKET_ID);
|
|
80
|
+
|
|
81
|
+
fun Cursor.columnIndex(): Int =
|
|
82
|
+
getColumnIndexOrThrow(column)
|
|
83
|
+
|
|
84
|
+
fun Cursor.getString(): String? =
|
|
85
|
+
getString(columnIndex())
|
|
86
|
+
|
|
87
|
+
fun Cursor.getInt(): Int? =
|
|
88
|
+
getInt(columnIndex())
|
|
89
|
+
|
|
90
|
+
fun Cursor.getLong(): Long? =
|
|
91
|
+
getLong(columnIndex())
|
|
92
|
+
|
|
93
|
+
companion object {
|
|
94
|
+
fun projection(includeDuration: Boolean): Array<String> =
|
|
95
|
+
values()
|
|
96
|
+
.filter { includeDuration || it != Duration }
|
|
97
|
+
.map { it.column }
|
|
98
|
+
.toTypedArray()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -7,7 +7,9 @@ import expo.modules.medialibrary.next.objects.asset.delegates.AssetDelegate
|
|
|
7
7
|
import expo.modules.medialibrary.next.objects.wrappers.RelativePath
|
|
8
8
|
import expo.modules.medialibrary.next.objects.wrappers.MediaType
|
|
9
9
|
import expo.modules.medialibrary.next.objects.wrappers.MimeType
|
|
10
|
+
import expo.modules.medialibrary.next.records.AssetInfo
|
|
10
11
|
import expo.modules.medialibrary.next.records.Location
|
|
12
|
+
import expo.modules.medialibrary.next.records.Shape
|
|
11
13
|
import kotlinx.coroutines.Dispatchers
|
|
12
14
|
import kotlinx.coroutines.withContext
|
|
13
15
|
|
|
@@ -29,6 +31,9 @@ class Asset(val assetDelegate: AssetDelegate) : SharedObject() {
|
|
|
29
31
|
suspend fun getWidth(): Int =
|
|
30
32
|
assetDelegate.getWidth()
|
|
31
33
|
|
|
34
|
+
suspend fun getShape(): Shape? =
|
|
35
|
+
assetDelegate.getShape()
|
|
36
|
+
|
|
32
37
|
suspend fun getMediaType(): MediaType =
|
|
33
38
|
assetDelegate.getMediaType()
|
|
34
39
|
|
|
@@ -38,6 +43,9 @@ class Asset(val assetDelegate: AssetDelegate) : SharedObject() {
|
|
|
38
43
|
suspend fun getUri(): Uri =
|
|
39
44
|
assetDelegate.getUri()
|
|
40
45
|
|
|
46
|
+
suspend fun getInfo(): AssetInfo =
|
|
47
|
+
assetDelegate.getInfo()
|
|
48
|
+
|
|
41
49
|
suspend fun getMimeType(): MimeType =
|
|
42
50
|
assetDelegate.getMimeType()
|
|
43
51
|
|
|
@@ -6,7 +6,9 @@ import expo.modules.medialibrary.next.objects.wrappers.RelativePath
|
|
|
6
6
|
import expo.modules.medialibrary.next.objects.asset.Asset
|
|
7
7
|
import expo.modules.medialibrary.next.objects.wrappers.MediaType
|
|
8
8
|
import expo.modules.medialibrary.next.objects.wrappers.MimeType
|
|
9
|
+
import expo.modules.medialibrary.next.records.AssetInfo
|
|
9
10
|
import expo.modules.medialibrary.next.records.Location
|
|
11
|
+
import expo.modules.medialibrary.next.records.Shape
|
|
10
12
|
|
|
11
13
|
interface AssetDelegate {
|
|
12
14
|
val contentUri: Uri
|
|
@@ -15,9 +17,11 @@ interface AssetDelegate {
|
|
|
15
17
|
suspend fun getFilename(): String
|
|
16
18
|
suspend fun getHeight(): Int
|
|
17
19
|
suspend fun getWidth(): Int
|
|
20
|
+
suspend fun getShape(): Shape?
|
|
18
21
|
suspend fun getMediaType(): MediaType
|
|
19
22
|
suspend fun getModificationTime(): Long?
|
|
20
23
|
suspend fun getUri(): Uri
|
|
24
|
+
suspend fun getInfo(): AssetInfo
|
|
21
25
|
suspend fun getMimeType(): MimeType
|
|
22
26
|
suspend fun getLocation(): Location?
|
|
23
27
|
suspend fun getExif(): Bundle
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
package expo.modules.medialibrary.next.objects.asset.delegates
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
-
import android.graphics.BitmapFactory
|
|
5
4
|
import android.net.Uri
|
|
6
5
|
import android.os.Build
|
|
7
6
|
import android.os.Bundle
|
|
8
7
|
import androidx.annotation.DeprecatedSinceApi
|
|
9
|
-
import androidx.core.net.toUri
|
|
10
8
|
import androidx.exifinterface.media.ExifInterface
|
|
11
9
|
import expo.modules.medialibrary.next.exceptions.AssetCouldNotBeCreated
|
|
12
10
|
import expo.modules.medialibrary.next.exceptions.AssetPropertyNotFoundException
|
|
@@ -16,10 +14,11 @@ import expo.modules.medialibrary.next.extensions.resolver.deleteBy
|
|
|
16
14
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDisplayName
|
|
17
15
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDuration
|
|
18
16
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetHeight
|
|
19
|
-
import expo.modules.medialibrary.next.extensions.resolver.queryAssetModificationTime
|
|
20
|
-
import expo.modules.medialibrary.next.extensions.resolver.queryAssetPath
|
|
21
17
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetWidth
|
|
22
|
-
import expo.modules.medialibrary.next.extensions.resolver.
|
|
18
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetData
|
|
19
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDateModified
|
|
20
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDateTaken
|
|
21
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetMediaStoreItem
|
|
23
22
|
import expo.modules.medialibrary.next.extensions.safeCopy
|
|
24
23
|
import expo.modules.medialibrary.next.extensions.safeMove
|
|
25
24
|
import expo.modules.medialibrary.next.extensions.scanFile
|
|
@@ -30,7 +29,9 @@ import expo.modules.medialibrary.next.objects.asset.deleters.AssetDeleter
|
|
|
30
29
|
import expo.modules.medialibrary.next.objects.wrappers.MediaType
|
|
31
30
|
import expo.modules.medialibrary.next.objects.wrappers.MimeType
|
|
32
31
|
import expo.modules.medialibrary.next.permissions.SystemPermissionsDelegate
|
|
32
|
+
import expo.modules.medialibrary.next.records.AssetInfo
|
|
33
33
|
import expo.modules.medialibrary.next.records.Location
|
|
34
|
+
import expo.modules.medialibrary.next.records.Shape
|
|
34
35
|
import kotlinx.coroutines.Dispatchers
|
|
35
36
|
import kotlinx.coroutines.ensureActive
|
|
36
37
|
import kotlinx.coroutines.withContext
|
|
@@ -38,8 +39,6 @@ import java.io.File
|
|
|
38
39
|
import java.lang.ref.WeakReference
|
|
39
40
|
import kotlin.collections.component1
|
|
40
41
|
import kotlin.collections.component2
|
|
41
|
-
import kotlin.time.DurationUnit
|
|
42
|
-
import kotlin.time.toDuration
|
|
43
42
|
|
|
44
43
|
@DeprecatedSinceApi(Build.VERSION_CODES.Q)
|
|
45
44
|
class AssetLegacyDelegate(
|
|
@@ -63,20 +62,21 @@ class AssetLegacyDelegate(
|
|
|
63
62
|
override var contentUri: Uri = contentUri
|
|
64
63
|
private set
|
|
65
64
|
|
|
65
|
+
private val mediaStoreToAssetAdapter by lazy {
|
|
66
|
+
MediaStoreToAssetAdapter(contextRef.getOrThrow())
|
|
67
|
+
}
|
|
68
|
+
|
|
66
69
|
override suspend fun getCreationTime(): Long? {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.takeIf { it != 0L }
|
|
70
|
+
val mediaStoreDateTaken = contentResolver.queryAssetDateTaken(contentUri)
|
|
71
|
+
return mediaStoreToAssetAdapter.transformCreationTime(mediaStoreDateTaken)
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
override suspend fun getDuration(): Long? {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.queryAssetDuration(contentUri)
|
|
76
|
-
.takeIf { it != 0L }
|
|
77
|
-
} else {
|
|
78
|
-
null
|
|
75
|
+
if (getMediaType() != MediaType.VIDEO) {
|
|
76
|
+
return null
|
|
79
77
|
}
|
|
78
|
+
val mediaStoreDuration = contentResolver.queryAssetDuration(contentUri)
|
|
79
|
+
return mediaStoreToAssetAdapter.transformDuration(mediaStoreDuration)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
override suspend fun getFilename(): String =
|
|
@@ -84,39 +84,61 @@ class AssetLegacyDelegate(
|
|
|
84
84
|
?: throw AssetPropertyNotFoundException("Filename")
|
|
85
85
|
|
|
86
86
|
override suspend fun getHeight(): Int {
|
|
87
|
-
val
|
|
87
|
+
val mediaStoreHeight = contentResolver.queryAssetHeight(contentUri)
|
|
88
|
+
return mediaStoreToAssetAdapter.transformHeight(mediaStoreHeight, contentUri)
|
|
88
89
|
?: throw AssetPropertyNotFoundException("Height")
|
|
89
|
-
// If height is not saved to the database
|
|
90
|
-
if (getMediaType() == MediaType.IMAGE && height <= 0) {
|
|
91
|
-
return downloadBitmapAndGet { it.outHeight }
|
|
92
|
-
}
|
|
93
|
-
return height
|
|
94
90
|
}
|
|
95
91
|
|
|
96
92
|
override suspend fun getWidth(): Int {
|
|
97
|
-
val
|
|
93
|
+
val mediaStoreWidth = contentResolver.queryAssetWidth(contentUri)
|
|
94
|
+
return mediaStoreToAssetAdapter.transformWidth(mediaStoreWidth, contentUri)
|
|
98
95
|
?: throw AssetPropertyNotFoundException("Width")
|
|
99
|
-
if (getMediaType() == MediaType.IMAGE && width <= 0) {
|
|
100
|
-
return downloadBitmapAndGet { it.outWidth }
|
|
101
|
-
}
|
|
102
|
-
return width
|
|
103
96
|
}
|
|
104
97
|
|
|
105
|
-
|
|
106
|
-
val
|
|
107
|
-
val
|
|
108
|
-
|
|
109
|
-
return extract(options)
|
|
98
|
+
override suspend fun getShape(): Shape? {
|
|
99
|
+
val width = getWidth()
|
|
100
|
+
val height = getHeight()
|
|
101
|
+
return Shape(width, height).takeIf { width > 0 && height > 0 }
|
|
110
102
|
}
|
|
111
103
|
|
|
112
104
|
override suspend fun getMediaType(): MediaType =
|
|
113
105
|
MediaType.fromContentUri(contentUri)
|
|
114
106
|
|
|
115
|
-
override suspend fun getModificationTime(): Long?
|
|
116
|
-
contentResolver.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
107
|
+
override suspend fun getModificationTime(): Long? {
|
|
108
|
+
val mediaStoreDateModified = contentResolver.queryAssetDateModified(contentUri)
|
|
109
|
+
return mediaStoreToAssetAdapter.transformModificationTime(mediaStoreDateModified)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override suspend fun getUri(): Uri {
|
|
113
|
+
// e.g. storage/emulated/0/Android/data/expo/files/[ROOT_ALBUM]/[ALBUM_NAME]
|
|
114
|
+
val mediaStoreData = contentResolver.queryAssetData(contentUri)
|
|
115
|
+
// e.g. file:///storage/emulated/0/Android/data/expo/files/[ROOT_ALBUM]/[ALBUM_NAME]
|
|
116
|
+
return mediaStoreToAssetAdapter.transformUri(mediaStoreData)
|
|
117
|
+
?: throw AssetPropertyNotFoundException("Uri")
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
override suspend fun getInfo(): AssetInfo {
|
|
121
|
+
val mediaStoreItem = contentResolver.queryAssetMediaStoreItem(contentUri)
|
|
122
|
+
?: throw AssetPropertyNotFoundException("Info")
|
|
123
|
+
val mediaType = getMediaType()
|
|
124
|
+
val height = mediaStoreToAssetAdapter.transformHeight(mediaStoreItem.height, contentUri)
|
|
125
|
+
val width = mediaStoreToAssetAdapter.transformWidth(mediaStoreItem.width, contentUri)
|
|
126
|
+
return AssetInfo(
|
|
127
|
+
id = contentUri,
|
|
128
|
+
mediaType = mediaType,
|
|
129
|
+
creationTime = mediaStoreToAssetAdapter.transformCreationTime(mediaStoreItem.dateTaken),
|
|
130
|
+
modificationTime = mediaStoreToAssetAdapter.transformModificationTime(mediaStoreItem.dateModified),
|
|
131
|
+
duration = mediaStoreToAssetAdapter.transformDuration(mediaStoreItem.duration),
|
|
132
|
+
filename = mediaStoreItem.displayName
|
|
133
|
+
?: throw AssetPropertyNotFoundException("Filename"),
|
|
134
|
+
height = height
|
|
135
|
+
?: throw AssetPropertyNotFoundException("Height"),
|
|
136
|
+
width = width
|
|
137
|
+
?: throw AssetPropertyNotFoundException("Width"),
|
|
138
|
+
uri = mediaStoreToAssetAdapter.transformUri(mediaStoreItem.data)
|
|
139
|
+
?: throw AssetPropertyNotFoundException("Uri")
|
|
140
|
+
)
|
|
141
|
+
}
|
|
120
142
|
|
|
121
143
|
override suspend fun getMimeType(): MimeType {
|
|
122
144
|
return contentResolver.getType(contentUri)?.let { MimeType(it) }
|
|
@@ -158,18 +180,9 @@ class AssetLegacyDelegate(
|
|
|
158
180
|
assetDeleter.delete(contentUri)
|
|
159
181
|
}
|
|
160
182
|
|
|
161
|
-
override suspend fun getUri(): Uri {
|
|
162
|
-
// e.g. storage/emulated/0/Android/data/expo/files/[ROOT_ALBUM]/[ALBUM_NAME]
|
|
163
|
-
val path = contentResolver.queryAssetPath(contentUri)
|
|
164
|
-
?: throw AssetPropertyNotFoundException("Uri")
|
|
165
|
-
// e.g. file:///storage/emulated/0/Android/data/expo/files/[ROOT_ALBUM]/[ALBUM_NAME]
|
|
166
|
-
val uri = File(path).toUri()
|
|
167
|
-
return uri
|
|
168
|
-
}
|
|
169
|
-
|
|
170
183
|
override suspend fun move(relativePath: RelativePath) = withContext(Dispatchers.IO) {
|
|
171
184
|
systemPermissionsDelegate.requireWritePermissions()
|
|
172
|
-
val path = contentResolver.
|
|
185
|
+
val path = contentResolver.queryAssetData(contentUri)
|
|
173
186
|
?: throw AssetPropertyNotFoundException("Asset path")
|
|
174
187
|
val newFile = File(path).safeMove(File(relativePath.toFilePath()))
|
|
175
188
|
contentResolver.deleteBy(path)
|
|
@@ -179,7 +192,7 @@ class AssetLegacyDelegate(
|
|
|
179
192
|
}
|
|
180
193
|
|
|
181
194
|
override suspend fun copy(relativePath: RelativePath): Asset = withContext(Dispatchers.IO) {
|
|
182
|
-
val path = contentResolver.
|
|
195
|
+
val path = contentResolver.queryAssetData(contentUri)
|
|
183
196
|
?: throw AssetPropertyNotFoundException("Asset path")
|
|
184
197
|
val newFile = File(path).safeCopy(File(relativePath.toFilePath()))
|
|
185
198
|
val (_, uri) = contextRef.getOrThrow().scanFile(newFile.path, null)
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
package expo.modules.medialibrary.next.objects.asset.delegates
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
-
import android.graphics.BitmapFactory
|
|
5
4
|
import androidx.exifinterface.media.ExifInterface
|
|
6
5
|
import android.net.Uri
|
|
7
6
|
import android.os.Build
|
|
8
7
|
import android.os.Bundle
|
|
9
8
|
import androidx.annotation.RequiresApi
|
|
10
|
-
import androidx.core.net.toUri
|
|
11
9
|
import expo.modules.medialibrary.next.exceptions.AssetPropertyNotFoundException
|
|
12
10
|
import expo.modules.medialibrary.next.exceptions.ContentResolverNotObtainedException
|
|
13
11
|
import expo.modules.medialibrary.next.extensions.getOrThrow
|
|
@@ -17,10 +15,11 @@ import expo.modules.medialibrary.next.extensions.resolver.publishPendingAsset
|
|
|
17
15
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDisplayName
|
|
18
16
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDuration
|
|
19
17
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetHeight
|
|
20
|
-
import expo.modules.medialibrary.next.extensions.resolver.queryAssetModificationTime
|
|
21
|
-
import expo.modules.medialibrary.next.extensions.resolver.queryAssetPath
|
|
22
18
|
import expo.modules.medialibrary.next.extensions.resolver.queryAssetWidth
|
|
23
|
-
import expo.modules.medialibrary.next.extensions.resolver.
|
|
19
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetData
|
|
20
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDateModified
|
|
21
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetDateTaken
|
|
22
|
+
import expo.modules.medialibrary.next.extensions.resolver.queryAssetMediaStoreItem
|
|
24
23
|
import expo.modules.medialibrary.next.extensions.resolver.updateRelativePath
|
|
25
24
|
import expo.modules.medialibrary.next.objects.wrappers.RelativePath
|
|
26
25
|
import expo.modules.medialibrary.next.objects.asset.Asset
|
|
@@ -29,17 +28,16 @@ import expo.modules.medialibrary.next.objects.asset.deleters.AssetDeleter
|
|
|
29
28
|
import expo.modules.medialibrary.next.objects.wrappers.MediaType
|
|
30
29
|
import expo.modules.medialibrary.next.objects.wrappers.MimeType
|
|
31
30
|
import expo.modules.medialibrary.next.permissions.MediaStorePermissionsDelegate
|
|
31
|
+
import expo.modules.medialibrary.next.records.AssetInfo
|
|
32
32
|
import expo.modules.medialibrary.next.records.Location
|
|
33
|
+
import expo.modules.medialibrary.next.records.Shape
|
|
33
34
|
import kotlinx.coroutines.Dispatchers
|
|
34
35
|
import kotlinx.coroutines.ensureActive
|
|
35
36
|
import kotlinx.coroutines.withContext
|
|
36
|
-
import java.io.File
|
|
37
37
|
import java.lang.ref.WeakReference
|
|
38
38
|
import kotlin.collections.component1
|
|
39
39
|
import kotlin.collections.component2
|
|
40
40
|
import kotlin.let
|
|
41
|
-
import kotlin.time.DurationUnit
|
|
42
|
-
import kotlin.time.toDuration
|
|
43
41
|
|
|
44
42
|
@RequiresApi(Build.VERSION_CODES.Q)
|
|
45
43
|
class AssetModernDelegate(
|
|
@@ -55,20 +53,21 @@ class AssetModernDelegate(
|
|
|
55
53
|
.getOrThrow()
|
|
56
54
|
.contentResolver ?: throw ContentResolverNotObtainedException()
|
|
57
55
|
|
|
56
|
+
private val mediaStoreToAssetAdapter by lazy {
|
|
57
|
+
MediaStoreToAssetAdapter(contextRef.getOrThrow())
|
|
58
|
+
}
|
|
59
|
+
|
|
58
60
|
override suspend fun getCreationTime(): Long? {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.takeIf { it != 0L }
|
|
61
|
+
val mediaStoreDateTaken = contentResolver.queryAssetDateTaken(contentUri)
|
|
62
|
+
return mediaStoreToAssetAdapter.transformCreationTime(mediaStoreDateTaken)
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
override suspend fun getDuration(): Long? {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.queryAssetDuration(contentUri)
|
|
68
|
-
.takeIf { it != 0L }
|
|
69
|
-
} else {
|
|
70
|
-
null
|
|
66
|
+
if (getMediaType() != MediaType.VIDEO) {
|
|
67
|
+
return null
|
|
71
68
|
}
|
|
69
|
+
val mediaStoreDuration = contentResolver.queryAssetDuration(contentUri)
|
|
70
|
+
return mediaStoreToAssetAdapter.transformDuration(mediaStoreDuration)
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
override suspend fun getFilename(): String =
|
|
@@ -76,45 +75,60 @@ class AssetModernDelegate(
|
|
|
76
75
|
?: throw AssetPropertyNotFoundException("Filename")
|
|
77
76
|
|
|
78
77
|
override suspend fun getHeight(): Int {
|
|
79
|
-
val
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return downloadBitmapAndGet { it.outHeight }
|
|
83
|
-
}
|
|
84
|
-
return height ?: throw AssetPropertyNotFoundException("Height")
|
|
78
|
+
val mediaStoreHeight = contentResolver.queryAssetHeight(contentUri)
|
|
79
|
+
return mediaStoreToAssetAdapter.transformHeight(mediaStoreHeight, contentUri)
|
|
80
|
+
?: throw AssetPropertyNotFoundException("Height")
|
|
85
81
|
}
|
|
86
82
|
|
|
87
83
|
override suspend fun getWidth(): Int {
|
|
88
|
-
val
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
return width ?: throw AssetPropertyNotFoundException("Width")
|
|
84
|
+
val mediaStoreWidth = contentResolver.queryAssetWidth(contentUri)
|
|
85
|
+
return mediaStoreToAssetAdapter.transformWidth(mediaStoreWidth, contentUri)
|
|
86
|
+
?: throw AssetPropertyNotFoundException("Width")
|
|
93
87
|
}
|
|
94
88
|
|
|
95
|
-
|
|
96
|
-
val
|
|
97
|
-
val
|
|
98
|
-
|
|
99
|
-
return extract(options)
|
|
89
|
+
override suspend fun getShape(): Shape? {
|
|
90
|
+
val width = getWidth()
|
|
91
|
+
val height = getHeight()
|
|
92
|
+
return Shape(width, height).takeIf { width > 0 && height > 0 }
|
|
100
93
|
}
|
|
101
94
|
|
|
102
95
|
override suspend fun getMediaType(): MediaType =
|
|
103
96
|
MediaType.fromContentUri(contentUri)
|
|
104
97
|
|
|
105
|
-
override suspend fun getModificationTime(): Long?
|
|
106
|
-
contentResolver.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
?.inWholeMilliseconds
|
|
98
|
+
override suspend fun getModificationTime(): Long? {
|
|
99
|
+
val mediaStoreDateModified = contentResolver.queryAssetDateModified(contentUri)
|
|
100
|
+
return mediaStoreToAssetAdapter.transformModificationTime(mediaStoreDateModified)
|
|
101
|
+
}
|
|
110
102
|
|
|
111
103
|
override suspend fun getUri(): Uri {
|
|
112
104
|
// e.g. storage/emulated/0/Android/data/expo/files/[ROOT_ALBUM]/[ALBUM_NAME]
|
|
113
|
-
val
|
|
114
|
-
?: throw AssetPropertyNotFoundException("Uri")
|
|
105
|
+
val mediaStoreData = contentResolver.queryAssetData(contentUri)
|
|
115
106
|
// e.g. file:///storage/emulated/0/Android/data/expo/files/[ROOT_ALBUM]/[ALBUM_NAME]
|
|
116
|
-
|
|
117
|
-
|
|
107
|
+
return mediaStoreToAssetAdapter.transformUri(mediaStoreData)
|
|
108
|
+
?: throw AssetPropertyNotFoundException("Uri")
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
override suspend fun getInfo(): AssetInfo {
|
|
112
|
+
val mediaStoreItem = contentResolver.queryAssetMediaStoreItem(contentUri)
|
|
113
|
+
?: throw AssetPropertyNotFoundException("Info")
|
|
114
|
+
val mediaType = getMediaType()
|
|
115
|
+
val height = mediaStoreToAssetAdapter.transformHeight(mediaStoreItem.height, contentUri)
|
|
116
|
+
val width = mediaStoreToAssetAdapter.transformWidth(mediaStoreItem.width, contentUri)
|
|
117
|
+
return AssetInfo(
|
|
118
|
+
id = contentUri,
|
|
119
|
+
mediaType = mediaType,
|
|
120
|
+
creationTime = mediaStoreToAssetAdapter.transformCreationTime(mediaStoreItem.dateTaken),
|
|
121
|
+
modificationTime = mediaStoreToAssetAdapter.transformModificationTime(mediaStoreItem.dateModified),
|
|
122
|
+
duration = mediaStoreToAssetAdapter.transformDuration(mediaStoreItem.duration),
|
|
123
|
+
filename = mediaStoreItem.displayName
|
|
124
|
+
?: throw AssetPropertyNotFoundException("Filename"),
|
|
125
|
+
height = height
|
|
126
|
+
?: throw AssetPropertyNotFoundException("Height"),
|
|
127
|
+
width = width
|
|
128
|
+
?: throw AssetPropertyNotFoundException("Width"),
|
|
129
|
+
uri = mediaStoreToAssetAdapter.transformUri(mediaStoreItem.data)
|
|
130
|
+
?: throw AssetPropertyNotFoundException("Uri")
|
|
131
|
+
)
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
override suspend fun getMimeType(): MimeType {
|