diff --git a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/api/IntOrStringSerializer.kt b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/api/IntOrStringSerializer.kt
new file mode 100644
index 00000000000..98bb51e0034
--- /dev/null
+++ b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/api/IntOrStringSerializer.kt
@@ -0,0 +1,52 @@
+/*
+ * Infomaniak Mail - Android
+ * Copyright (C) 2026 Infomaniak Network SA
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.infomaniak.mail.data.api
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import kotlinx.serialization.json.JsonDecoder
+import kotlinx.serialization.json.JsonPrimitive
+import kotlinx.serialization.json.intOrNull
+
+object IntOrStringSerializer : KSerializer {
+
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("IntOrString", PrimitiveKind.STRING)
+
+ override fun deserialize(decoder: Decoder): String {
+ return if (decoder is JsonDecoder) {
+ val jsonPrimitive = decoder.decodeJsonElement() as? JsonPrimitive
+ ?: throw SerializationException("Expected a primitive element for id")
+ if (jsonPrimitive.isString) {
+ jsonPrimitive.content
+ } else {
+ jsonPrimitive.intOrNull?.toString() ?: jsonPrimitive.content
+ }
+ } else {
+ decoder.decodeString()
+ }
+ }
+
+ override fun serialize(encoder: Encoder, value: String) {
+ encoder.encodeString(value)
+ }
+}
diff --git a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/Contact.kt b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/Contact.kt
index cd9a7643f93..15db60deb7e 100644
--- a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/Contact.kt
+++ b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/Contact.kt
@@ -19,6 +19,7 @@
package com.infomaniak.mail.data.models.correspondent
+import com.infomaniak.mail.data.api.IntOrStringSerializer
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.serializers.RealmListKSerializer
import io.realm.kotlin.types.RealmList
@@ -28,6 +29,8 @@ import kotlinx.serialization.UseSerializers
@Serializable
data class Contact(
+ @Serializable(with = IntOrStringSerializer::class)
+ val id: String? = null,
val name: String = "",
val emails: RealmList = realmListOf(),
val avatar: String? = null,
diff --git a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/MergedContact.kt b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/MergedContact.kt
index b04f34e17cd..60dda35a66d 100644
--- a/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/MergedContact.kt
+++ b/OldKotlin/realm-models/src/main/kotlin/com/infomaniak/mail/data/models/correspondent/MergedContact.kt
@@ -46,6 +46,9 @@ class MergedContact() : RealmObject, Correspondent, ContactAutocompletable {
var comesFromApi: Boolean = false // In opposition to coming from the phone's address book
private set
+ var remoteContactId: String? = null
+ private set
+
var remoteContactGroupIds: RealmList = realmListOf()
var addressbookIds: RealmList = realmListOf()
@@ -78,6 +81,7 @@ class MergedContact() : RealmObject, Correspondent, ContactAutocompletable {
this.contactedTimes = apiContact.contactedTimes?.get(email)
this.other = apiContact.other
+ this.remoteContactId = apiContact.id
this.comesFromApi = comesFromApi
@@ -113,6 +117,7 @@ class MergedContact() : RealmObject, Correspondent, ContactAutocompletable {
avatar = apiContact.avatar
comesFromApi = true
}
+ remoteContactId = apiContact.id
addressbookIds += realmListOf(apiContact.addressbookId)
remoteContactGroupIds += apiContact.remoteContactGroupIds
}
diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt b/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt
index 0448ff0d957..4b4d13c881e 100644
--- a/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt
+++ b/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt
@@ -202,7 +202,7 @@ object RealmDatabase {
private object RealmConfig {
//region Configurations versions
- const val USER_INFO_SCHEMA_VERSION = 5L
+ const val USER_INFO_SCHEMA_VERSION = 6L
const val MAILBOX_INFO_SCHEMA_VERSION = 19L
const val MAILBOX_CONTENT_SCHEMA_VERSION = 37L
//endregion
diff --git a/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt b/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt
index 593c8024f5b..86ade845785 100644
--- a/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt
+++ b/app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt
@@ -307,6 +307,11 @@ class MainViewModel @Inject constructor(
//region Merged Contacts
val mergedContactsLive: LiveData = avatarMergedContactData.mergedContactLiveData
+
+ fun shouldShowAddToContacts(recipient: Recipient): Boolean {
+ val remoteContactId = mergedContactController.getMergedContactFromEmail(recipient.email)?.remoteContactId
+ return remoteContactId.isNullOrBlank()
+ }
//endregion
//region Share Thread URL
diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/DetailedContactBottomSheetDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/DetailedContactBottomSheetDialog.kt
index b3409727062..331af385ce1 100644
--- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/DetailedContactBottomSheetDialog.kt
+++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/DetailedContactBottomSheetDialog.kt
@@ -63,6 +63,7 @@ class DetailedContactBottomSheetDialog : ActionsBottomSheetDialog() {
val bimi = navigationArgs.bimi
containerInfoCertified.isVisible = bimi?.isCertified == true
contactDetails.setCorrespondent(navigationArgs.recipient, bimi)
+ addToContacts.isVisible = mainViewModel.shouldShowAddToContacts(navigationArgs.recipient)
setupListeners()