kopia lustrzana https://github.com/ryukoposting/Signal-Android
Reduce profile avatar disk reads.
rodzic
2f17963b2b
commit
819f7a170f
|
@ -92,7 +92,7 @@ public final class AvatarPreviewActivity extends PassphraseRequiredActivity {
|
||||||
RecipientId recipientId = RecipientId.from(getIntent().getStringExtra(RECIPIENT_ID_EXTRA));
|
RecipientId recipientId = RecipientId.from(getIntent().getStringExtra(RECIPIENT_ID_EXTRA));
|
||||||
|
|
||||||
Recipient.live(recipientId).observe(this, recipient -> {
|
Recipient.live(recipientId).observe(this, recipient -> {
|
||||||
ContactPhoto contactPhoto = recipient.isSelf() ? new ProfileContactPhoto(recipient, recipient.getProfileAvatar())
|
ContactPhoto contactPhoto = recipient.isSelf() ? new ProfileContactPhoto(recipient)
|
||||||
: recipient.getContactPhoto();
|
: recipient.getContactPhoto();
|
||||||
FallbackContactPhoto fallbackPhoto = recipient.isSelf() ? new ResourceContactPhoto(R.drawable.ic_profile_outline_40, R.drawable.ic_profile_outline_20, R.drawable.ic_person_large)
|
FallbackContactPhoto fallbackPhoto = recipient.isSelf() ? new ResourceContactPhoto(R.drawable.ic_profile_outline_40, R.drawable.ic_profile_outline_20, R.drawable.ic_person_large)
|
||||||
: recipient.getFallbackContactPhoto();
|
: recipient.getFallbackContactPhoto();
|
||||||
|
|
|
@ -160,8 +160,7 @@ public final class AvatarImageView extends AppCompatImageView {
|
||||||
private void setAvatar(@NonNull GlideRequests requestManager, @Nullable Recipient recipient, @NonNull AvatarOptions avatarOptions) {
|
private void setAvatar(@NonNull GlideRequests requestManager, @Nullable Recipient recipient, @NonNull AvatarOptions avatarOptions) {
|
||||||
if (recipient != null) {
|
if (recipient != null) {
|
||||||
RecipientContactPhoto photo = (recipient.isSelf() && avatarOptions.useSelfProfileAvatar) ? new RecipientContactPhoto(recipient,
|
RecipientContactPhoto photo = (recipient.isSelf() && avatarOptions.useSelfProfileAvatar) ? new RecipientContactPhoto(recipient,
|
||||||
new ProfileContactPhoto(Recipient.self(),
|
new ProfileContactPhoto(Recipient.self()))
|
||||||
Recipient.self().getProfileAvatar()))
|
|
||||||
: new RecipientContactPhoto(recipient);
|
: new RecipientContactPhoto(recipient);
|
||||||
|
|
||||||
boolean shouldBlur = recipient.shouldBlurAvatar();
|
boolean shouldBlur = recipient.shouldBlurAvatar();
|
||||||
|
|
|
@ -253,7 +253,7 @@ public class CallParticipantView extends ConstraintLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPipAvatar(@NonNull Recipient recipient) {
|
private void setPipAvatar(@NonNull Recipient recipient) {
|
||||||
ContactPhoto contactPhoto = recipient.isSelf() ? new ProfileContactPhoto(Recipient.self(), Recipient.self().getProfileAvatar())
|
ContactPhoto contactPhoto = recipient.isSelf() ? new ProfileContactPhoto(Recipient.self())
|
||||||
: recipient.getContactPhoto();
|
: recipient.getContactPhoto();
|
||||||
FallbackContactPhoto fallbackPhoto = recipient.getFallbackContactPhoto(FALLBACK_PHOTO_PROVIDER);
|
FallbackContactPhoto fallbackPhoto = recipient.getFallbackContactPhoto(FALLBACK_PHOTO_PROVIDER);
|
||||||
|
|
||||||
|
|
|
@ -505,7 +505,7 @@ public class WebRtcCallView extends ConstraintLayout {
|
||||||
largeLocalRenderNoVideoAvatar.setVisibility(View.VISIBLE);
|
largeLocalRenderNoVideoAvatar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
GlideApp.with(getContext().getApplicationContext())
|
GlideApp.with(getContext().getApplicationContext())
|
||||||
.load(new ProfileContactPhoto(localCallParticipant.getRecipient(), localCallParticipant.getRecipient().getProfileAvatar()))
|
.load(new ProfileContactPhoto(localCallParticipant.getRecipient()))
|
||||||
.transform(new CenterCrop(), new BlurTransformation(getContext(), 0.25f, BlurTransformation.MAX_RADIUS))
|
.transform(new CenterCrop(), new BlurTransformation(getContext(), 0.25f, BlurTransformation.MAX_RADIUS))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.into(largeLocalRenderNoVideoAvatar);
|
.into(largeLocalRenderNoVideoAvatar);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.signal.libsignal.protocol.util.ByteUtil;
|
import org.signal.libsignal.protocol.util.ByteUtil;
|
||||||
|
import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
@ -21,10 +22,12 @@ public class ProfileContactPhoto implements ContactPhoto {
|
||||||
|
|
||||||
private final @NonNull Recipient recipient;
|
private final @NonNull Recipient recipient;
|
||||||
private final @NonNull String avatarObject;
|
private final @NonNull String avatarObject;
|
||||||
|
private final @NonNull ProfileAvatarFileDetails profileAvatarFileDetails;
|
||||||
|
|
||||||
public ProfileContactPhoto(@NonNull Recipient recipient, @Nullable String avatarObject) {
|
public ProfileContactPhoto(@NonNull Recipient recipient) {
|
||||||
this.recipient = recipient;
|
this.recipient = recipient;
|
||||||
this.avatarObject = avatarObject == null ? "" : avatarObject;
|
this.avatarObject = recipient.getProfileAvatar() == null ? "" : recipient.getProfileAvatar();
|
||||||
|
this.profileAvatarFileDetails = recipient.getProfileAvatarFileDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,7 +49,7 @@ public class ProfileContactPhoto implements ContactPhoto {
|
||||||
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
|
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
|
||||||
messageDigest.update(recipient.getId().serialize().getBytes());
|
messageDigest.update(recipient.getId().serialize().getBytes());
|
||||||
messageDigest.update(avatarObject.getBytes());
|
messageDigest.update(avatarObject.getBytes());
|
||||||
messageDigest.update(ByteUtil.longToByteArray(getFileLastModified()));
|
messageDigest.update(profileAvatarFileDetails.getDiskCacheKeyBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,15 +59,11 @@ public class ProfileContactPhoto implements ContactPhoto {
|
||||||
ProfileContactPhoto that = (ProfileContactPhoto) o;
|
ProfileContactPhoto that = (ProfileContactPhoto) o;
|
||||||
return recipient.equals(that.recipient) &&
|
return recipient.equals(that.recipient) &&
|
||||||
avatarObject.equals(that.avatarObject) &&
|
avatarObject.equals(that.avatarObject) &&
|
||||||
getFileLastModified() == that.getFileLastModified();
|
profileAvatarFileDetails.equals(that.profileAvatarFileDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(recipient, avatarObject, getFileLastModified());
|
return Objects.hash(recipient, avatarObject, profileAvatarFileDetails);
|
||||||
}
|
|
||||||
|
|
||||||
private long getFileLastModified() {
|
|
||||||
return AvatarHelper.getLastModified(ApplicationDependencies.getApplication(), recipient.getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3609,7 +3609,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
systemContactUri = cursor.requireString(SYSTEM_CONTACT_URI),
|
systemContactUri = cursor.requireString(SYSTEM_CONTACT_URI),
|
||||||
signalProfileName = ProfileName.fromParts(cursor.requireString(PROFILE_GIVEN_NAME), cursor.requireString(PROFILE_FAMILY_NAME)),
|
signalProfileName = ProfileName.fromParts(cursor.requireString(PROFILE_GIVEN_NAME), cursor.requireString(PROFILE_FAMILY_NAME)),
|
||||||
signalProfileAvatar = cursor.requireString(SIGNAL_PROFILE_AVATAR),
|
signalProfileAvatar = cursor.requireString(SIGNAL_PROFILE_AVATAR),
|
||||||
hasProfileImage = AvatarHelper.hasAvatar(context, recipientId),
|
profileAvatarFileDetails = AvatarHelper.getAvatarFileDetails(context, recipientId),
|
||||||
profileSharing = cursor.requireBoolean(PROFILE_SHARING),
|
profileSharing = cursor.requireBoolean(PROFILE_SHARING),
|
||||||
lastProfileFetch = cursor.requireLong(LAST_PROFILE_FETCH),
|
lastProfileFetch = cursor.requireLong(LAST_PROFILE_FETCH),
|
||||||
notificationChannel = cursor.requireString(NOTIFICATION_CHANNEL),
|
notificationChannel = cursor.requireString(NOTIFICATION_CHANNEL),
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.thoughtcrime.securesms.database.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details related to the current avatar profile image file that would be returned via [org.thoughtcrime.securesms.profiles.AvatarHelper.getAvatarFile]
|
||||||
|
* at the time this [org.thoughtcrime.securesms.recipients.Recipient] was loaded/refreshed from the database.
|
||||||
|
*/
|
||||||
|
data class ProfileAvatarFileDetails(
|
||||||
|
val hashId: Long,
|
||||||
|
val lastModified: Long
|
||||||
|
) {
|
||||||
|
fun getDiskCacheKeyBytes(): ByteArray {
|
||||||
|
return toString().toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasFile(): Boolean {
|
||||||
|
return this != NO_DETAILS
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmField
|
||||||
|
val NO_DETAILS = ProfileAvatarFileDetails(0, 0)
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,8 +55,7 @@ data class RecipientRecord(
|
||||||
val signalProfileName: ProfileName,
|
val signalProfileName: ProfileName,
|
||||||
@get:JvmName("getProfileAvatar")
|
@get:JvmName("getProfileAvatar")
|
||||||
val signalProfileAvatar: String?,
|
val signalProfileAvatar: String?,
|
||||||
@get:JvmName("hasProfileImage")
|
val profileAvatarFileDetails: ProfileAvatarFileDetails,
|
||||||
val hasProfileImage: Boolean,
|
|
||||||
@get:JvmName("isProfileSharing")
|
@get:JvmName("isProfileSharing")
|
||||||
val profileSharing: Boolean,
|
val profileSharing: Boolean,
|
||||||
val lastProfileFetch: Long,
|
val lastProfileFetch: Long,
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class InsightsRepository implements InsightsDashboardViewModel.Repository
|
||||||
Recipient self = Recipient.self().resolve();
|
Recipient self = Recipient.self().resolve();
|
||||||
String name = Optional.of(self.getDisplayName(context)).orElse("");
|
String name = Optional.of(self.getDisplayName(context)).orElse("");
|
||||||
|
|
||||||
return new InsightsUserAvatar(new ProfileContactPhoto(self, self.getProfileAvatar()),
|
return new InsightsUserAvatar(new ProfileContactPhoto(self),
|
||||||
self.getAvatarColor(),
|
self.getAvatarColor(),
|
||||||
new GeneratedContactPhoto(name, R.drawable.ic_profile_outline_40));
|
new GeneratedContactPhoto(name, R.drawable.ic_profile_outline_40));
|
||||||
}, avatarConsumer::accept);
|
}, avatarConsumer::accept);
|
||||||
|
|
|
@ -36,7 +36,7 @@ fun Drawable?.toLargeBitmap(context: Context): Bitmap? {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Recipient.getContactDrawable(context: Context): Drawable? {
|
fun Recipient.getContactDrawable(context: Context): Drawable? {
|
||||||
val contactPhoto: ContactPhoto? = if (isSelf) ProfileContactPhoto(this, profileAvatar) else contactPhoto
|
val contactPhoto: ContactPhoto? = if (isSelf) ProfileContactPhoto(this) else contactPhoto
|
||||||
val fallbackContactPhoto: FallbackContactPhoto = if (isSelf) getFallback(context) else fallbackContactPhoto
|
val fallbackContactPhoto: FallbackContactPhoto = if (isSelf) getFallback(context) else fallbackContactPhoto
|
||||||
return if (contactPhoto != null) {
|
return if (contactPhoto != null) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
||||||
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
|
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
|
||||||
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
|
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream;
|
||||||
|
import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails;
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
|
@ -103,6 +104,14 @@ public class AvatarHelper {
|
||||||
return avatarFile.exists() && avatarFile.length() > 0;
|
return avatarFile.exists() && avatarFile.length() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static @NonNull ProfileAvatarFileDetails getAvatarFileDetails(@NonNull Context context, @NonNull RecipientId recipientId) {
|
||||||
|
File avatarFile = getAvatarFile(context, recipientId);
|
||||||
|
if (avatarFile.exists() && avatarFile.length() > 0) {
|
||||||
|
return new ProfileAvatarFileDetails(avatarFile.hashCode(), avatarFile.lastModified());
|
||||||
|
}
|
||||||
|
return ProfileAvatarFileDetails.NO_DETAILS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a stream for an avatar. If there is no avatar, the stream will likely throw an
|
* Retrieves a stream for an avatar. If there is no avatar, the stream will likely throw an
|
||||||
* IOException. It is recommended to call {@link #hasAvatar(Context, RecipientId)} first.
|
* IOException. It is recommended to call {@link #hasAvatar(Context, RecipientId)} first.
|
||||||
|
@ -174,19 +183,6 @@ public class AvatarHelper {
|
||||||
return ModernEncryptingPartOutputStream.createFor(attachmentSecret, targetFile, true).second;
|
return ModernEncryptingPartOutputStream.createFor(attachmentSecret, targetFile, true).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the timestamp of when the avatar was last modified, or zero if the avatar doesn't exist.
|
|
||||||
*/
|
|
||||||
public static long getLastModified(@NonNull Context context, @NonNull RecipientId recipientId) {
|
|
||||||
File file = getAvatarFile(context, recipientId);
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
return file.lastModified();
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link StreamDetails} for the local user's own avatar, or null if one does not exist.
|
* Returns a {@link StreamDetails} for the local user's own avatar, or null if one does not exist.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessM
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
||||||
|
import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails;
|
||||||
import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras;
|
import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
|
@ -110,7 +111,7 @@ public class Recipient {
|
||||||
private final Uri contactUri;
|
private final Uri contactUri;
|
||||||
private final ProfileName signalProfileName;
|
private final ProfileName signalProfileName;
|
||||||
private final String profileAvatar;
|
private final String profileAvatar;
|
||||||
private final boolean hasProfileImage;
|
private final ProfileAvatarFileDetails profileAvatarFileDetails;
|
||||||
private final boolean profileSharing;
|
private final boolean profileSharing;
|
||||||
private final long lastProfileFetch;
|
private final long lastProfileFetch;
|
||||||
private final String notificationChannel;
|
private final String notificationChannel;
|
||||||
|
@ -388,7 +389,7 @@ public class Recipient {
|
||||||
this.contactUri = null;
|
this.contactUri = null;
|
||||||
this.signalProfileName = ProfileName.EMPTY;
|
this.signalProfileName = ProfileName.EMPTY;
|
||||||
this.profileAvatar = null;
|
this.profileAvatar = null;
|
||||||
this.hasProfileImage = false;
|
this.profileAvatarFileDetails = ProfileAvatarFileDetails.NO_DETAILS;
|
||||||
this.profileSharing = false;
|
this.profileSharing = false;
|
||||||
this.lastProfileFetch = 0;
|
this.lastProfileFetch = 0;
|
||||||
this.notificationChannel = null;
|
this.notificationChannel = null;
|
||||||
|
@ -446,7 +447,7 @@ public class Recipient {
|
||||||
this.contactUri = details.contactUri;
|
this.contactUri = details.contactUri;
|
||||||
this.signalProfileName = details.profileName;
|
this.signalProfileName = details.profileName;
|
||||||
this.profileAvatar = details.profileAvatar;
|
this.profileAvatar = details.profileAvatar;
|
||||||
this.hasProfileImage = details.hasProfileImage;
|
this.profileAvatarFileDetails = details.profileAvatarFileDetails;
|
||||||
this.profileSharing = details.profileSharing;
|
this.profileSharing = details.profileSharing;
|
||||||
this.lastProfileFetch = details.lastProfileFetch;
|
this.lastProfileFetch = details.lastProfileFetch;
|
||||||
this.notificationChannel = details.notificationChannel;
|
this.notificationChannel = details.notificationChannel;
|
||||||
|
@ -811,6 +812,10 @@ public class Recipient {
|
||||||
return profileAvatar;
|
return profileAvatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NonNull ProfileAvatarFileDetails getProfileAvatarFileDetails() {
|
||||||
|
return profileAvatarFileDetails;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isProfileSharing() {
|
public boolean isProfileSharing() {
|
||||||
return profileSharing;
|
return profileSharing;
|
||||||
}
|
}
|
||||||
|
@ -907,7 +912,7 @@ public class Recipient {
|
||||||
if (isSelf) return null;
|
if (isSelf) return null;
|
||||||
else if (isGroupInternal() && groupAvatarId.isPresent()) return new GroupRecordContactPhoto(groupId, groupAvatarId.get());
|
else if (isGroupInternal() && groupAvatarId.isPresent()) return new GroupRecordContactPhoto(groupId, groupAvatarId.get());
|
||||||
else if (systemContactPhoto != null && SignalStore.settings().isPreferSystemContactPhotos()) return new SystemContactPhoto(id, systemContactPhoto, 0);
|
else if (systemContactPhoto != null && SignalStore.settings().isPreferSystemContactPhotos()) return new SystemContactPhoto(id, systemContactPhoto, 0);
|
||||||
else if (profileAvatar != null && hasProfileImage) return new ProfileContactPhoto(this, profileAvatar);
|
else if (profileAvatar != null && profileAvatarFileDetails.hasFile()) return new ProfileContactPhoto(this);
|
||||||
else if (systemContactPhoto != null) return new SystemContactPhoto(id, systemContactPhoto, 0);
|
else if (systemContactPhoto != null) return new SystemContactPhoto(id, systemContactPhoto, 0);
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
@ -1263,7 +1268,7 @@ public class Recipient {
|
||||||
blocked == other.blocked &&
|
blocked == other.blocked &&
|
||||||
muteUntil == other.muteUntil &&
|
muteUntil == other.muteUntil &&
|
||||||
expireMessages == other.expireMessages &&
|
expireMessages == other.expireMessages &&
|
||||||
hasProfileImage == other.hasProfileImage &&
|
Objects.equals(profileAvatarFileDetails, other.profileAvatarFileDetails) &&
|
||||||
profileSharing == other.profileSharing &&
|
profileSharing == other.profileSharing &&
|
||||||
lastProfileFetch == other.lastProfileFetch &&
|
lastProfileFetch == other.lastProfileFetch &&
|
||||||
forceSmsSelection == other.forceSmsSelection &&
|
forceSmsSelection == other.forceSmsSelection &&
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
|
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||||
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
||||||
|
import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails;
|
||||||
import org.thoughtcrime.securesms.database.model.RecipientRecord;
|
import org.thoughtcrime.securesms.database.model.RecipientRecord;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
|
@ -60,7 +61,7 @@ public class RecipientDetails {
|
||||||
final byte[] profileKey;
|
final byte[] profileKey;
|
||||||
final ExpiringProfileKeyCredential expiringProfileKeyCredential;
|
final ExpiringProfileKeyCredential expiringProfileKeyCredential;
|
||||||
final String profileAvatar;
|
final String profileAvatar;
|
||||||
final boolean hasProfileImage;
|
final ProfileAvatarFileDetails profileAvatarFileDetails;
|
||||||
final boolean profileSharing;
|
final boolean profileSharing;
|
||||||
final long lastProfileFetch;
|
final long lastProfileFetch;
|
||||||
final boolean systemContact;
|
final boolean systemContact;
|
||||||
|
@ -123,7 +124,7 @@ public class RecipientDetails {
|
||||||
this.profileKey = record.getProfileKey();
|
this.profileKey = record.getProfileKey();
|
||||||
this.expiringProfileKeyCredential = record.getExpiringProfileKeyCredential();
|
this.expiringProfileKeyCredential = record.getExpiringProfileKeyCredential();
|
||||||
this.profileAvatar = record.getProfileAvatar();
|
this.profileAvatar = record.getProfileAvatar();
|
||||||
this.hasProfileImage = record.hasProfileImage();
|
this.profileAvatarFileDetails = record.getProfileAvatarFileDetails();
|
||||||
this.profileSharing = record.isProfileSharing();
|
this.profileSharing = record.isProfileSharing();
|
||||||
this.lastProfileFetch = record.getLastProfileFetch();
|
this.lastProfileFetch = record.getLastProfileFetch();
|
||||||
this.systemContact = systemContact;
|
this.systemContact = systemContact;
|
||||||
|
@ -181,7 +182,7 @@ public class RecipientDetails {
|
||||||
this.profileKey = null;
|
this.profileKey = null;
|
||||||
this.expiringProfileKeyCredential = null;
|
this.expiringProfileKeyCredential = null;
|
||||||
this.profileAvatar = null;
|
this.profileAvatar = null;
|
||||||
this.hasProfileImage = false;
|
this.profileAvatarFileDetails = ProfileAvatarFileDetails.NO_DETAILS;
|
||||||
this.profileSharing = false;
|
this.profileSharing = false;
|
||||||
this.lastProfileFetch = 0;
|
this.lastProfileFetch = 0;
|
||||||
this.systemContact = true;
|
this.systemContact = true;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public final class AvatarUtil {
|
||||||
ContactPhoto photo;
|
ContactPhoto photo;
|
||||||
|
|
||||||
if (recipient.isSelf()) {
|
if (recipient.isSelf()) {
|
||||||
photo = new ProfileContactPhoto(Recipient.self(), Recipient.self().getProfileAvatar());
|
photo = new ProfileContactPhoto(Recipient.self());
|
||||||
} else if (recipient.getContactPhoto() == null) {
|
} else if (recipient.getContactPhoto() == null) {
|
||||||
target.setImageDrawable(null);
|
target.setImageDrawable(null);
|
||||||
target.setBackgroundColor(ContextCompat.getColor(target.getContext(), R.color.black));
|
target.setBackgroundColor(ContextCompat.getColor(target.getContext(), R.color.black));
|
||||||
|
@ -150,7 +150,7 @@ public final class AvatarUtil {
|
||||||
private static <T> GlideRequest<T> request(@NonNull GlideRequest<T> glideRequest, @NonNull Context context, @NonNull Recipient recipient, boolean loadSelf, int targetSize) {
|
private static <T> GlideRequest<T> request(@NonNull GlideRequest<T> glideRequest, @NonNull Context context, @NonNull Recipient recipient, boolean loadSelf, int targetSize) {
|
||||||
final ContactPhoto photo;
|
final ContactPhoto photo;
|
||||||
if (Recipient.self().equals(recipient) && loadSelf) {
|
if (Recipient.self().equals(recipient) && loadSelf) {
|
||||||
photo = new ProfileContactPhoto(recipient, recipient.getProfileAvatar());
|
photo = new ProfileContactPhoto(recipient);
|
||||||
} else {
|
} else {
|
||||||
photo = recipient.getContactPhoto();
|
photo = recipient.getContactPhoto();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp;
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
|
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.SystemContactPhoto;
|
import org.thoughtcrime.securesms.contacts.avatars.SystemContactPhoto;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
|
import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
|
||||||
|
import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
@ -43,11 +44,13 @@ public final class ConversationShortcutPhoto implements Key {
|
||||||
|
|
||||||
private final Recipient recipient;
|
private final Recipient recipient;
|
||||||
private final String avatarObject;
|
private final String avatarObject;
|
||||||
|
private final ProfileAvatarFileDetails profileAvatarFileDetails;
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public ConversationShortcutPhoto(@NonNull Recipient recipient) {
|
public ConversationShortcutPhoto(@NonNull Recipient recipient) {
|
||||||
this.recipient = recipient.resolve();
|
this.recipient = recipient.resolve();
|
||||||
this.avatarObject = Util.firstNonNull(recipient.getProfileAvatar(), "");
|
this.avatarObject = Util.firstNonNull(recipient.getProfileAvatar(), "");
|
||||||
|
this.profileAvatarFileDetails = recipient.getProfileAvatarFileDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,7 +58,7 @@ public final class ConversationShortcutPhoto implements Key {
|
||||||
messageDigest.update(recipient.getDisplayName(ApplicationDependencies.getApplication()).getBytes());
|
messageDigest.update(recipient.getDisplayName(ApplicationDependencies.getApplication()).getBytes());
|
||||||
messageDigest.update(avatarObject.getBytes());
|
messageDigest.update(avatarObject.getBytes());
|
||||||
messageDigest.update(isSystemContactPhoto() ? (byte) 1 : (byte) 0);
|
messageDigest.update(isSystemContactPhoto() ? (byte) 1 : (byte) 0);
|
||||||
messageDigest.update(ByteUtil.longToByteArray(getFileLastModified()));
|
messageDigest.update(profileAvatarFileDetails.getDiskCacheKeyBytes());
|
||||||
messageDigest.update(ByteUtil.longToByteArray(VERSION));
|
messageDigest.update(ByteUtil.longToByteArray(VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,22 +70,18 @@ public final class ConversationShortcutPhoto implements Key {
|
||||||
return Objects.equals(recipient, that.recipient) &&
|
return Objects.equals(recipient, that.recipient) &&
|
||||||
Objects.equals(avatarObject, that.avatarObject) &&
|
Objects.equals(avatarObject, that.avatarObject) &&
|
||||||
isSystemContactPhoto() == that.isSystemContactPhoto() &&
|
isSystemContactPhoto() == that.isSystemContactPhoto() &&
|
||||||
getFileLastModified() == that.getFileLastModified();
|
Objects.equals(profileAvatarFileDetails, that.profileAvatarFileDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(recipient, avatarObject, isSystemContactPhoto(), getFileLastModified());
|
return Objects.hash(recipient, avatarObject, isSystemContactPhoto(), profileAvatarFileDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSystemContactPhoto() {
|
private boolean isSystemContactPhoto() {
|
||||||
return recipient.getContactPhoto() instanceof SystemContactPhoto;
|
return recipient.getContactPhoto() instanceof SystemContactPhoto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getFileLastModified() {
|
|
||||||
return AvatarHelper.getLastModified(ApplicationDependencies.getApplication(), recipient.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Loader implements ModelLoader<ConversationShortcutPhoto, Bitmap> {
|
public static final class Loader implements ModelLoader<ConversationShortcutPhoto, Bitmap> {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential
|
||||||
import org.thoughtcrime.securesms.badges.models.Badge
|
import org.thoughtcrime.securesms.badges.models.Badge
|
||||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||||
|
import org.thoughtcrime.securesms.database.model.ProfileAvatarFileDetails
|
||||||
import org.thoughtcrime.securesms.database.model.RecipientRecord
|
import org.thoughtcrime.securesms.database.model.RecipientRecord
|
||||||
import org.thoughtcrime.securesms.groups.GroupId
|
import org.thoughtcrime.securesms.groups.GroupId
|
||||||
import org.thoughtcrime.securesms.profiles.ProfileName
|
import org.thoughtcrime.securesms.profiles.ProfileName
|
||||||
|
@ -55,7 +56,7 @@ object RecipientDatabaseTestUtils {
|
||||||
systemContactUri: String? = null,
|
systemContactUri: String? = null,
|
||||||
signalProfileName: ProfileName = ProfileName.EMPTY,
|
signalProfileName: ProfileName = ProfileName.EMPTY,
|
||||||
signalProfileAvatar: String? = null,
|
signalProfileAvatar: String? = null,
|
||||||
hasProfileImage: Boolean = false,
|
profileAvatarFileDetails: ProfileAvatarFileDetails = ProfileAvatarFileDetails.NO_DETAILS,
|
||||||
profileSharing: Boolean = false,
|
profileSharing: Boolean = false,
|
||||||
lastProfileFetch: Long = 0L,
|
lastProfileFetch: Long = 0L,
|
||||||
notificationChannel: String? = null,
|
notificationChannel: String? = null,
|
||||||
|
@ -119,7 +120,7 @@ object RecipientDatabaseTestUtils {
|
||||||
systemContactUri,
|
systemContactUri,
|
||||||
signalProfileName,
|
signalProfileName,
|
||||||
signalProfileAvatar,
|
signalProfileAvatar,
|
||||||
hasProfileImage,
|
profileAvatarFileDetails,
|
||||||
profileSharing,
|
profileSharing,
|
||||||
lastProfileFetch,
|
lastProfileFetch,
|
||||||
notificationChannel,
|
notificationChannel,
|
||||||
|
|
Ładowanie…
Reference in New Issue