diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt index d881d9d33c..c800823b4c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt @@ -131,8 +131,10 @@ class ProfilePictureView @JvmOverloads constructor( this.recipient = Recipient.from(context, Address.fromSerialized(publicKey), false) this.recipient!! } + if (profilePicturesCache[imageView] == recipient) return - profilePicturesCache[imageView] = recipient + // recipient is mutable so without cloning it the line above always returns true as the changes to the underlying recipient happens on both shared instances + profilePicturesCache[imageView] = recipient.clone() val signalProfilePicture = recipient.contactPhoto val avatar = (signalProfilePicture as? ProfileContactPhoto)?.avatarObject diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index b51680fc32..9bdd5c33b0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -238,11 +238,6 @@ open class Storage @Inject constructor( return Profile(displayName, profileKey, profilePictureUrl) } - override fun setProfileAvatar(recipient: Recipient, profileAvatar: String?) { - val database = recipientDatabase - database.setProfileAvatar(recipient, profileAvatar) - } - override fun setProfilePicture(recipient: Recipient, newProfilePicture: String?, newProfileKey: ByteArray?) { val db = recipientDatabase db.setProfileAvatar(recipient, newProfilePicture) @@ -263,7 +258,7 @@ open class Storage @Inject constructor( preferences.setProfilePictureURL(newProfilePicture) if (newProfileKey != null) { - JobQueue.shared.add(RetrieveProfileAvatarJob(newProfilePicture, ourRecipient.address)) + JobQueue.shared.add(RetrieveProfileAvatarJob(newProfilePicture, ourRecipient.address, newProfileKey)) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt index b9f778c49e..a86e932970 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt @@ -69,12 +69,9 @@ class ProfileManager @Inject constructor( .getAllJobs(RetrieveProfileAvatarJob.KEY).any { (it.value as? RetrieveProfileAvatarJob)?.recipientAddress == recipient.address } - val resolved = recipient.resolve() - storage.get().setProfilePicture( - recipient = resolved, - newProfileKey = profileKey, - newProfilePicture = profilePictureURL - ) + + recipient.resolve() + val accountID = recipient.address.serialize() var contact = contactDatabase.getContactWithAccountID(accountID) if (contact == null) contact = Contact(accountID) @@ -86,7 +83,7 @@ class ProfileManager @Inject constructor( } contactUpdatedInternal(contact) if (!hasPendingDownload) { - val job = RetrieveProfileAvatarJob(profilePictureURL, recipient.address) + val job = RetrieveProfileAvatarJob(profilePictureURL, recipient.address, profileKey) JobQueue.shared.add(job) } } diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 59a56a5736..67edecc877 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -47,7 +47,6 @@ interface StorageProtocol { fun getUserED25519KeyPair(): KeyPair? fun getUserX25519KeyPair(): ECKeyPair fun getUserProfile(): Profile - fun setProfileAvatar(recipient: Recipient, profileAvatar: String?) fun setProfilePicture(recipient: Recipient, newProfilePicture: String?, newProfileKey: ByteArray?) fun setBlocksCommunityMessageRequests(recipient: Recipient, blocksMessageRequests: Boolean) fun setUserProfilePicture(newProfilePicture: String?, newProfileKey: ByteArray?) diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt index 618a31b5e2..fbdd151b60 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/RetrieveProfileAvatarJob.kt @@ -19,7 +19,10 @@ import java.io.FileOutputStream import java.io.InputStream import java.util.concurrent.ConcurrentSkipListSet -class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipientAddress: Address): Job { +class RetrieveProfileAvatarJob( + private val profileAvatar: String?, val recipientAddress: Address, + private val profileKey: ByteArray? +): Job { override var delegate: JobDelegate? = null override var id: String? = null override var failureCount: Int = 0 @@ -32,6 +35,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient // Keys used for database storage private const val PROFILE_AVATAR_KEY = "profileAvatar" private const val RECEIPIENT_ADDRESS_KEY = "recipient" + private const val PROFILE_KEY = "profileKey" val errorUrls = ConcurrentSkipListSet() @@ -43,7 +47,6 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient val context = MessagingModuleConfiguration.shared.context val storage = MessagingModuleConfiguration.shared.storage val recipient = Recipient.from(context, recipientAddress, true) - val profileKey = recipient.resolve().profileKey if (profileKey == null || (profileKey.size != 32 && profileKey.size != 16)) { return delegate.handleJobFailedPermanently(this, dispatcherName, Exception("Recipient profile key is gone!")) @@ -69,7 +72,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient } AvatarHelper.delete(context, recipient.address) - storage.setProfileAvatar(recipient, null) + storage.setProfilePicture(recipient, null, null) return } @@ -87,7 +90,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient setProfilePictureURL(context, profileAvatar) } - storage.setProfileAvatar(recipient, profileAvatar) + storage.setProfilePicture(recipient, profileAvatar, profileKey) } catch (e: Exception) { Log.e("Loki", "Failed to download profile avatar", e) if (failureCount + 1 >= maxFailureCount) { @@ -101,10 +104,15 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient } override fun serialize(): Data { - return Data.Builder() - .putString(PROFILE_AVATAR_KEY, profileAvatar) - .putString(RECEIPIENT_ADDRESS_KEY, recipientAddress.serialize()) - .build() + val data = Data.Builder() + .putString(PROFILE_AVATAR_KEY, profileAvatar) + .putString(RECEIPIENT_ADDRESS_KEY, recipientAddress.serialize()) + + if (profileKey != null) { + data.putByteArray(PROFILE_KEY, profileKey) + } + + return data.build() } override fun getFactoryKey(): String { @@ -115,7 +123,8 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient override fun create(data: Data): RetrieveProfileAvatarJob { val profileAvatar = if (data.hasString(PROFILE_AVATAR_KEY)) { data.getString(PROFILE_AVATAR_KEY) } else { null } val recipientAddress = Address.fromSerialized(data.getString(RECEIPIENT_ADDRESS_KEY)) - return RetrieveProfileAvatarJob(profileAvatar, recipientAddress) + val profileKey = data.getByteArray(PROFILE_KEY) + return RetrieveProfileAvatarJob(profileAvatar, recipientAddress, profileKey) } } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java index a9186066ea..a0666512ee 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java +++ b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java @@ -59,7 +59,7 @@ import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ExecutionException; -public class Recipient implements RecipientModifiedListener { +public class Recipient implements RecipientModifiedListener, Cloneable { private static final String TAG = Recipient.class.getSimpleName(); private static final RecipientProvider provider = new RecipientProvider(); @@ -1156,5 +1156,9 @@ public class Recipient implements RecipientModifiedListener { } - + @NonNull + @Override + public Recipient clone() throws CloneNotSupportedException { + return (Recipient) super.clone(); + } }