expo-contacts 14.0.4 → 14.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,13 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 14.0.5 — 2025-01-31
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - [Android] Fixed saving a contact with photos on Android. ([#34432](https://github.com/expo/expo/pull/34432) by [@chrfalch](https://github.com/chrfalch))
18
+ - Fixed corrupted contact after `updateContactAsync`. ([#34186](https://github.com/expo/expo/pull/34186) by [@freeboub](https://github.com/34186))
19
+
13
20
  ## 14.0.4 — 2025-01-27
14
21
 
15
22
  ### 🎉 New features
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'host.exp.exponent'
4
- version = '14.0.4'
4
+ version = '14.0.5'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -14,7 +14,7 @@ android {
14
14
  namespace "expo.modules.contacts"
15
15
  defaultConfig {
16
16
  versionCode 29
17
- versionName "14.0.4"
17
+ versionName "14.0.5"
18
18
  }
19
19
  }
20
20
 
@@ -22,6 +22,8 @@ import expo.modules.contacts.models.PhoneNumberModel
22
22
  import expo.modules.contacts.models.PostalAddressModel
23
23
  import expo.modules.contacts.models.RelationshipModel
24
24
  import expo.modules.contacts.models.UrlAddressModel
25
+ import expo.modules.kotlin.AppContext
26
+ import expo.modules.kotlin.exception.Exceptions
25
27
  import java.io.ByteArrayOutputStream
26
28
  import java.text.ParseException
27
29
  import java.text.SimpleDateFormat
@@ -29,7 +31,7 @@ import java.util.Calendar
29
31
  import java.util.Locale
30
32
 
31
33
  // TODO: MaidenName Nickname
32
- class Contact(var contactId: String) {
34
+ class Contact(var contactId: String, var appContext: AppContext) {
33
35
  private var rawContactId: String? = null
34
36
  var lookupKey: String? = null
35
37
  private var displayName: String? = null
@@ -285,17 +287,42 @@ class Contact(var contactId: String) {
285
287
  .build()
286
288
  )
287
289
  }
290
+
291
+ // Flush all data from linked db
292
+ rawContactId?.let { id ->
293
+ baseModelsContentType.forEach {
294
+ ops.add(getFlushOperation(it, id))
295
+ }
296
+ }
297
+
298
+ // add updated data
288
299
  for (map in baseModels) {
289
300
  for (item in map) {
290
- ops.add(item.getDeleteOperation(rawContactId!!))
291
301
  ops.add(item.getInsertOperation(rawContactId))
292
302
  }
293
303
  }
294
304
  return ops
295
305
  }
296
306
 
307
+ private fun getFlushOperation(contentType: String, rawId: String): ContentProviderOperation {
308
+ return ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
309
+ .withSelection("${ContactsContract.Data.MIMETYPE}=? AND ${ContactsContract.Data.RAW_CONTACT_ID}=?", arrayOf(contentType, rawId))
310
+ .build()
311
+ }
312
+
297
313
  private val baseModels: Array<List<BaseModel>>
298
314
  get() = arrayOf(dates, emails, imAddresses, phones, addresses, relationships, urlAddresses, extraNames)
315
+ private val baseModelsContentType: Array<String>
316
+ get() = arrayOf(
317
+ CommonDataKinds.Event.CONTENT_ITEM_TYPE,
318
+ CommonDataKinds.Email.CONTENT_ITEM_TYPE,
319
+ CommonDataKinds.Im.CONTENT_ITEM_TYPE,
320
+ CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
321
+ CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE,
322
+ CommonDataKinds.Relation.CONTENT_ITEM_TYPE,
323
+ CommonDataKinds.Website.CONTENT_ITEM_TYPE,
324
+ CommonDataKinds.Nickname.CONTENT_ITEM_TYPE
325
+ )
299
326
 
300
327
  // convert to react native object
301
328
  @Throws(ParseException::class)
@@ -521,7 +548,10 @@ class Contact(var contactId: String) {
521
548
  }
522
549
 
523
550
  private fun getThumbnailBitmap(photoUri: String?): Bitmap {
524
- val path = Uri.parse(photoUri).path
525
- return BitmapFactory.decodeFile(path)
551
+ val context = appContext.reactContext ?: throw Exceptions.ReactContextLost()
552
+ val uri = Uri.parse(photoUri)
553
+ context.contentResolver.openInputStream(uri).use { inputStream ->
554
+ return BitmapFactory.decodeStream(inputStream)
555
+ }
526
556
  }
527
557
  }
@@ -326,7 +326,7 @@ class ContactsModule : Module() {
326
326
  get() = (appContext.reactContext ?: throw Exceptions.ReactContextLost()).contentResolver
327
327
 
328
328
  private fun mutateContact(initContact: Contact?, data: Map<String, Any>): Contact {
329
- val contact = initContact ?: Contact(UUID.randomUUID().toString())
329
+ val contact = initContact ?: Contact(UUID.randomUUID().toString(), appContext)
330
330
 
331
331
  data.safeGet<String>("firstName")?.let { contact.firstName = it }
332
332
  data.safeGet<String>("middleName")?.let { contact.middleName = it }
@@ -660,7 +660,7 @@ class ContactsModule : Module() {
660
660
  val contactId = cursor.getString(columnIndex)
661
661
 
662
662
  // add or update existing contact for iterating data based on contact id
663
- val contact = map.getOrPut(contactId) { Contact(contactId) }
663
+ val contact = map.getOrPut(contactId) { Contact(contactId, appContext) }
664
664
  contact.fromCursor(cursor)
665
665
  }
666
666
  return map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-contacts",
3
- "version": "14.0.4",
3
+ "version": "14.0.5",
4
4
  "description": "Provides access to the phone's system contacts.",
5
5
  "main": "build/Contacts.js",
6
6
  "types": "build/Contacts.d.ts",
@@ -40,5 +40,5 @@
40
40
  "expo": "*",
41
41
  "react-native": "*"
42
42
  },
43
- "gitHead": "3fd37fd31fd818d833e85c4723b1578010da6967"
43
+ "gitHead": "d13f18276d52b15263754f35ec72befcb2785104"
44
44
  }