Show contact profile photo instead of system contact.

This commit is contained in:
Alex Hart 2021-01-13 11:36:39 -04:00 committed by Greyson Parrelli
parent cee2702fdf
commit 2d20ceea01
10 changed files with 80 additions and 26 deletions

View file

@ -13,6 +13,8 @@ public final class SettingsValues extends SignalStoreValues {
public static final String LINK_PREVIEWS = "settings.link_previews";
public static final String KEEP_MESSAGES_DURATION = "settings.keep_messages_duration";
public static final String PREFER_SYSTEM_CONTACT_PHOTOS = "settings.prefer.system.contact.photos";
private static final String SIGNAL_BACKUP_DIRECTORY = "settings.signal.backup.directory";
private static final String SIGNAL_LATEST_BACKUP_DIRECTORY = "settings.signal.backup.directory,latest";
@ -69,6 +71,14 @@ public final class SettingsValues extends SignalStoreValues {
putString(SIGNAL_LATEST_BACKUP_DIRECTORY, uri.toString());
}
public void setPreferSystemContactPhotos(boolean preferSystemContactPhotos) {
putBoolean(PREFER_SYSTEM_CONTACT_PHOTOS, preferSystemContactPhotos);
}
public boolean isPreferSystemContactPhotos() {
return getBoolean(PREFER_SYSTEM_CONTACT_PHOTOS, false);
}
public @Nullable Uri getSignalBackupDirectory() {
return getUri(SIGNAL_BACKUP_DIRECTORY);
}

View file

@ -2,29 +2,26 @@ package org.thoughtcrime.securesms.preferences;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import org.greenrobot.eventbus.EventBus;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
import org.thoughtcrime.securesms.util.ConversationUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.webrtc.CallBandwidthMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.thoughtcrime.securesms.util.ThrottledDebouncer;
public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment {
private static final String PREFER_SYSTEM_CONTACT_PHOTOS = "pref_system_contact_photos";
private final ThrottledDebouncer refreshDebouncer = new ThrottledDebouncer(500);
@Override
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
@ -37,6 +34,14 @@ public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment {
return true;
});
findPreference(PREFER_SYSTEM_CONTACT_PHOTOS)
.setOnPreferenceChangeListener((preference, newValue) -> {
SignalStore.settings().setPreferSystemContactPhotos(newValue == Boolean.TRUE);
refreshDebouncer.publish(ConversationUtil::refreshRecipientShortcuts);
StorageSyncHelper.scheduleSyncForDataChange();
return true;
});
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.MESSAGE_BODY_TEXT_SIZE_PREF));
}

View file

@ -34,12 +34,14 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessM
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.phonenumbers.NumberUtil;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.StringUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.libsignal.util.guava.Preconditions;
@ -729,11 +731,12 @@ public class Recipient {
}
public @Nullable ContactPhoto getContactPhoto() {
if (isSelf) return null;
else if (isGroupInternal() && groupAvatarId.isPresent()) return new GroupRecordContactPhoto(groupId, groupAvatarId.get());
else if (systemContactPhoto != null) return new SystemContactPhoto(id, systemContactPhoto, 0);
else if (profileAvatar != null && hasProfileImage) return new ProfileContactPhoto(this, profileAvatar);
else return null;
if (isSelf) return null;
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 (profileAvatar != null && hasProfileImage) return new ProfileContactPhoto(this, profileAvatar);
else if (systemContactPhoto != null) return new SystemContactPhoto(id, systemContactPhoto, 0);
else return null;
}
public @Nullable Uri getMessageRingtone() {

View file

@ -70,8 +70,9 @@ class AccountConflictMerger implements StorageSyncHelper.ConflictMerger<SignalAc
boolean unlisted = remote.isPhoneNumberUnlisted();
List<PinnedConversation> pinnedConversations = remote.getPinnedConversations();
AccountRecord.PhoneNumberSharingMode phoneNumberSharingMode = remote.getPhoneNumberSharingMode();
boolean matchesRemote = doParamsMatch(remote, unknownFields, givenName, familyName, avatarUrlPath, profileKey, noteToSelfArchived, noteToSelfForcedUnread, readReceipts, typingIndicators, sealedSenderIndicators, linkPreviews, phoneNumberSharingMode, unlisted, pinnedConversations);
boolean matchesLocal = doParamsMatch(local, unknownFields, givenName, familyName, avatarUrlPath, profileKey, noteToSelfArchived, noteToSelfForcedUnread, readReceipts, typingIndicators, sealedSenderIndicators, linkPreviews, phoneNumberSharingMode, unlisted, pinnedConversations);
boolean preferContactAvatars = remote.isPreferContactAvatars();
boolean matchesRemote = doParamsMatch(remote, unknownFields, givenName, familyName, avatarUrlPath, profileKey, noteToSelfArchived, noteToSelfForcedUnread, readReceipts, typingIndicators, sealedSenderIndicators, linkPreviews, phoneNumberSharingMode, unlisted, pinnedConversations, preferContactAvatars);
boolean matchesLocal = doParamsMatch(local, unknownFields, givenName, familyName, avatarUrlPath, profileKey, noteToSelfArchived, noteToSelfForcedUnread, readReceipts, typingIndicators, sealedSenderIndicators, linkPreviews, phoneNumberSharingMode, unlisted, pinnedConversations, preferContactAvatars);
if (matchesRemote) {
return remote;
@ -94,6 +95,7 @@ class AccountConflictMerger implements StorageSyncHelper.ConflictMerger<SignalAc
.setPhoneNumberSharingMode(phoneNumberSharingMode)
.setUnlistedPhoneNumber(unlisted)
.setPinnedConversations(pinnedConversations)
.setPreferContactAvatars(preferContactAvatars)
.build();
}
}
@ -112,7 +114,8 @@ class AccountConflictMerger implements StorageSyncHelper.ConflictMerger<SignalAc
boolean linkPreviewsEnabled,
AccountRecord.PhoneNumberSharingMode phoneNumberSharingMode,
boolean unlistedPhoneNumber,
@NonNull List<PinnedConversation> pinnedConversations)
@NonNull List<PinnedConversation> pinnedConversations,
boolean preferContactAvatars)
{
return Arrays.equals(contact.serializeUnknownFields(), unknownFields) &&
Objects.equals(contact.getGivenName().or(""), givenName) &&
@ -127,6 +130,7 @@ class AccountConflictMerger implements StorageSyncHelper.ConflictMerger<SignalAc
contact.isLinkPreviewsEnabled() == linkPreviewsEnabled &&
contact.getPhoneNumberSharingMode() == phoneNumberSharingMode &&
contact.isPhoneNumberUnlisted() == unlistedPhoneNumber &&
contact.isPreferContactAvatars() == preferContactAvatars &&
Objects.equals(contact.getPinnedConversations(), pinnedConversations);
}
}

View file

@ -431,6 +431,7 @@ public final class StorageSyncHelper {
.setUnlistedPhoneNumber(SignalStore.phoneNumberPrivacy().getPhoneNumberListingMode().isUnlisted())
.setPhoneNumberSharingMode(StorageSyncModels.localToRemotePhoneNumberSharingMode(SignalStore.phoneNumberPrivacy().getPhoneNumberSharingMode()))
.setPinnedConversations(StorageSyncModels.localToRemotePinnedConversations(pinned))
.setPreferContactAvatars(SignalStore.settings().isPreferSystemContactPhotos())
.build();
return SignalStorageRecord.forAccount(account);
@ -452,6 +453,7 @@ public final class StorageSyncHelper {
SignalStore.settings().setLinkPreviewsEnabled(update.isLinkPreviewsEnabled());
SignalStore.phoneNumberPrivacy().setPhoneNumberListingMode(update.isPhoneNumberUnlisted() ? PhoneNumberPrivacyValues.PhoneNumberListingMode.UNLISTED : PhoneNumberPrivacyValues.PhoneNumberListingMode.LISTED);
SignalStore.phoneNumberPrivacy().setPhoneNumberSharingMode(StorageSyncModels.remoteToLocalPhoneNumberSharingMode(update.getPhoneNumberSharingMode()));
SignalStore.settings().setPreferSystemContactPhotos(update.isPreferContactAvatars());
if (fetchProfile && update.getAvatarUrlPath().isPresent()) {
ApplicationDependencies.getJobManager().add(new RetrieveProfileAvatarJob(Recipient.self(), update.getAvatarUrlPath().get()));

View file

@ -22,7 +22,9 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp;
import org.thoughtcrime.securesms.contacts.avatars.GeneratedContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.SystemContactPhoto;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequest;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
@ -42,12 +44,14 @@ public final class ConversationShortcutPhoto implements Key {
public ConversationShortcutPhoto(@NonNull Recipient recipient) {
this.recipient = recipient.resolve();
this.avatarObject = Util.firstNonNull(recipient.getProfileAvatar(), "");
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(recipient.getDisplayName(ApplicationDependencies.getApplication()).getBytes());
messageDigest.update(avatarObject.getBytes());
messageDigest.update(isSystemContactPhoto() ? (byte) 1 : (byte) 0);
messageDigest.update(ByteUtil.longToByteArray(getFileLastModified()));
}
@ -56,14 +60,19 @@ public final class ConversationShortcutPhoto implements Key {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConversationShortcutPhoto that = (ConversationShortcutPhoto) o;
return Objects.equals(recipient, that.recipient) &&
Objects.equals(avatarObject, that.avatarObject) &&
return Objects.equals(recipient, that.recipient) &&
Objects.equals(avatarObject, that.avatarObject) &&
isSystemContactPhoto() == that.isSystemContactPhoto() &&
getFileLastModified() == that.getFileLastModified();
}
@Override
public int hashCode() {
return Objects.hash(recipient, avatarObject, getFileLastModified());
return Objects.hash(recipient, avatarObject, isSystemContactPhoto(), getFileLastModified());
}
private boolean isSystemContactPhoto() {
return recipient.getContactPhoto() instanceof SystemContactPhoto;
}
private long getFileLastModified() {

View file

@ -2331,6 +2331,8 @@
<string name="preferences__use_signal_for_viewing_and_storing_all_incoming_multimedia_messages">Use Signal for all incoming multimedia messages</string>
<string name="preferences__pref_enter_sends_title">Enter key sends</string>
<string name="preferences__pressing_the_enter_key_will_send_text_messages">Pressing the Enter key will send text messages</string>
<string name="preferences__pref_use_address_book_photos">Use address book photos</string>
<string name="preferences__display_contact_photos_from_your_address_book_if_available">Display contact photos from your address book if available</string>
<string name="preferences__generate_link_previews">Generate link previews</string>
<string name="preferences__retrieve_link_previews_from_websites_for_messages">Retrieve link previews directly from websites for messages you send.</string>
<string name="preferences__choose_identity">Choose identity</string>

View file

@ -30,6 +30,12 @@
android:summary="@string/preferences__pressing_the_enter_key_will_send_text_messages"
android:title="@string/preferences__pref_enter_sends_title"/>
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_system_contact_photos"
android:summary="@string/preferences__display_contact_photos_from_your_address_book_if_available"
android:title="@string/preferences__pref_use_address_book_photos"/>
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/preference_divider"/>

View file

@ -24,17 +24,19 @@ public final class SignalAccountRecord implements SignalRecord {
private final Optional<String> avatarUrlPath;
private final Optional<byte[]> profileKey;
private final List<PinnedConversation> pinnedConversations;
private final boolean preferContactAvatars;
public SignalAccountRecord(StorageId id, AccountRecord proto) {
this.id = id;
this.proto = proto;
this.hasUnknownFields = ProtoUtil.hasUnknownFields(proto);
this.givenName = OptionalUtil.absentIfEmpty(proto.getGivenName());
this.familyName = OptionalUtil.absentIfEmpty(proto.getFamilyName());
this.profileKey = OptionalUtil.absentIfEmpty(proto.getProfileKey());
this.avatarUrlPath = OptionalUtil.absentIfEmpty(proto.getAvatarUrlPath());
this.pinnedConversations = new ArrayList<>(proto.getPinnedConversationsCount());
this.givenName = OptionalUtil.absentIfEmpty(proto.getGivenName());
this.familyName = OptionalUtil.absentIfEmpty(proto.getFamilyName());
this.profileKey = OptionalUtil.absentIfEmpty(proto.getProfileKey());
this.avatarUrlPath = OptionalUtil.absentIfEmpty(proto.getAvatarUrlPath());
this.pinnedConversations = new ArrayList<>(proto.getPinnedConversationsCount());
this.preferContactAvatars = proto.getPreferContactAvatars();
for (AccountRecord.PinnedConversation conversation : proto.getPinnedConversationsList()) {
pinnedConversations.add(PinnedConversation.fromRemote(conversation));
@ -106,6 +108,10 @@ public final class SignalAccountRecord implements SignalRecord {
return pinnedConversations;
}
public boolean isPreferContactAvatars() {
return preferContactAvatars;
}
AccountRecord toProto() {
return proto;
}
@ -300,6 +306,12 @@ public final class SignalAccountRecord implements SignalRecord {
return this;
}
public Builder setPreferContactAvatars(boolean preferContactAvatars) {
builder.setPreferContactAvatars(preferContactAvatars);
return this;
}
public SignalAccountRecord build() {
AccountRecord proto = builder.build();

View file

@ -134,4 +134,5 @@ message AccountRecord {
PhoneNumberSharingMode phoneNumberSharingMode = 12;
bool unlistedPhoneNumber = 13;
repeated PinnedConversation pinnedConversations = 14;
bool preferContactAvatars = 15;
}