mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 16:57:50 +00:00
Multi-device profile avatar.
This commit is contained in:
parent
9337a1d44a
commit
6e7b21e8b4
@ -41,6 +41,9 @@ import android.widget.Toast;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.thoughtcrime.securesms.components.RatingManager;
|
||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
||||
@ -52,6 +55,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
||||
import org.thoughtcrime.securesms.loki.AddPublicChatActivity;
|
||||
import org.thoughtcrime.securesms.loki.JazzIdenticonDrawable;
|
||||
import org.thoughtcrime.securesms.loki.RecipientAvatarModifiedEvent;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
@ -134,6 +138,18 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = this.getMenuInflater();
|
||||
@ -214,7 +230,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
Drawable fallback = primaryRecipient.getFallbackContactPhotoDrawable(this, false);
|
||||
|
||||
GlideApp.with(this)
|
||||
.load(new ProfileContactPhoto(primaryRecipient.getAddress(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this))))
|
||||
.load(primaryRecipient.getContactPhoto())
|
||||
.fallback(fallback)
|
||||
.error(fallback)
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
@ -321,4 +337,14 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
private void addNewPublicChat() {
|
||||
startActivity(new Intent(this, AddPublicChatActivity.class));
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onAvatarModified(RecipientAvatarModifiedEvent event) {
|
||||
Recipient recipient = event.getRecipient();
|
||||
String ourMasterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
|
||||
boolean isOurMasterDevice = ourMasterHexEncodedPublicKey != null && ourMasterHexEncodedPublicKey.equals(recipient.getAddress().serialize());
|
||||
if (recipient.isLocalNumber() || isOurMasterDevice) {
|
||||
initializeProfileIcon(recipient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
return false;
|
||||
}
|
||||
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceProfileKeyUpdateJob());
|
||||
// ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceProfileKeyUpdateJob());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -724,6 +724,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
handleUnknownGroupMessage(content, message.getMessage().getGroupInfo().get());
|
||||
}
|
||||
|
||||
String ourMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||
boolean isSenderMasterDevice = ourMasterDevice != null && ourMasterDevice.equals(content.getSender());
|
||||
if (message.getMessage().getProfileKey().isPresent()) {
|
||||
Recipient recipient = null;
|
||||
|
||||
@ -734,6 +736,16 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
if (recipient != null && !recipient.isSystemContact() && !recipient.isProfileSharing()) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
||||
}
|
||||
|
||||
// Loki - If we received a sync message from our master device then we need to extract the avatar url
|
||||
if (isSenderMasterDevice) {
|
||||
handleProfileKey(content, message.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Loki - Update display name from master device
|
||||
if (isSenderMasterDevice && content.senderDisplayName.isPresent() && content.senderDisplayName.get().length() > 0) {
|
||||
TextSecurePreferences.setProfileName(context, content.senderDisplayName.get());
|
||||
}
|
||||
|
||||
if (threadId != null) {
|
||||
@ -1142,7 +1154,10 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
if (content.senderDisplayName.isPresent() && content.senderDisplayName.get().length() > 0) {
|
||||
TextSecurePreferences.setProfileName(context, content.senderDisplayName.get());
|
||||
}
|
||||
|
||||
// Profile avatar updates
|
||||
if (content.getDataMessage().isPresent()) {
|
||||
handleProfileKey(content, content.getDataMessage().get());
|
||||
}
|
||||
// Contact sync
|
||||
if (content.getSyncMessage().isPresent() && content.getSyncMessage().get().getContacts().isPresent()) {
|
||||
handleSynchronizeContactMessage(content.getSyncMessage().get().getContacts().get());
|
||||
@ -1413,8 +1428,14 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
private void handleProfileKey(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message)
|
||||
{
|
||||
if (!message.getProfileKey().isPresent()) { return; }
|
||||
|
||||
/*
|
||||
If we get a profile key then we don't need to map it to the primary device.
|
||||
For now a profile key is mapped one-to-one to avoid secondary devices setting the incorrect avatar for a primary device.
|
||||
*/
|
||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||
Recipient recipient = getPrimaryDeviceRecipient(content.getSender());
|
||||
Recipient recipient = Recipient.from(context, Address.fromSerialized(content.getSender()), false);
|
||||
|
||||
if (recipient.getProfileKey() == null || !MessageDigest.isEqual(recipient.getProfileKey(), message.getProfileKey().get())) {
|
||||
database.setProfileKey(recipient, message.getProfileKey().get());
|
||||
|
@ -11,6 +11,8 @@ import nl.komponents.kovenant.toFailVoid
|
||||
import nl.komponents.kovenant.ui.successUi
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.PreKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.logging.Log
|
||||
@ -114,12 +116,16 @@ fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Conte
|
||||
fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: PairingAuthorisation): Promise<Unit, Exception> {
|
||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||
val address = SignalServiceAddress(contactHexEncodedPublicKey)
|
||||
val message = SignalServiceDataMessage.newBuilder().withBody(null).withPairingAuthorisation(authorisation)
|
||||
val message = SignalServiceDataMessage.newBuilder().withPairingAuthorisation(authorisation)
|
||||
// A REQUEST should always act as a friend request. A GRANT should always be replying back as a normal message.
|
||||
if (authorisation.type == PairingAuthorisation.Type.REQUEST) {
|
||||
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)
|
||||
message.asFriendRequest(true).withPreKeyBundle(preKeyBundle)
|
||||
} else {
|
||||
// Send over our profile key so that our linked device can get our profile picture
|
||||
message.withProfileKey(ProfileKeyUtil.getProfileKey(context))
|
||||
}
|
||||
|
||||
return try {
|
||||
Log.d("Loki", "Sending authorisation message to: $contactHexEncodedPublicKey.")
|
||||
val result = messageSender.sendMessage(0, address, Optional.absent<UnidentifiedAccessPair>(), message.build())
|
||||
|
@ -0,0 +1,5 @@
|
||||
package org.thoughtcrime.securesms.loki
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
data class RecipientAvatarModifiedEvent(val recipient: Recipient)
|
@ -20,6 +20,7 @@ import android.widget.Toast;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities;
|
||||
@ -80,13 +81,14 @@ public class ProfilePreference extends Preference {
|
||||
public void refresh() {
|
||||
if (profileNumberView == null) return;
|
||||
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext());
|
||||
String primaryDevicePublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(getContext());
|
||||
Context context = getContext();
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context);
|
||||
String primaryDevicePublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||
String publicKey = primaryDevicePublicKey != null ? primaryDevicePublicKey : userHexEncodedPublicKey;
|
||||
final Address localAddress = Address.fromSerialized(publicKey);
|
||||
final String profileName = TextSecurePreferences.getProfileName(getContext());
|
||||
final Recipient recipient = Recipient.from(context, localAddress, false);
|
||||
final String profileName = TextSecurePreferences.getProfileName(context);
|
||||
|
||||
Context context = getContext();
|
||||
containerView.setOnLongClickListener(v -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("Public Key", publicKey);
|
||||
@ -104,9 +106,9 @@ public class ProfilePreference extends Preference {
|
||||
});
|
||||
avatarView.setClipToOutline(true);
|
||||
|
||||
Drawable fallback = Recipient.from(context, localAddress, false).getFallbackContactPhotoDrawable(context, false);
|
||||
Drawable fallback = recipient.getFallbackContactPhotoDrawable(context, false);
|
||||
GlideApp.with(getContext().getApplicationContext())
|
||||
.load(new ProfileContactPhoto(localAddress, String.valueOf(TextSecurePreferences.getProfileAvatarId(getContext()))))
|
||||
.load(recipient.getContactPhoto())
|
||||
.fallback(fallback)
|
||||
.error(fallback)
|
||||
.circleCrop()
|
||||
|
@ -26,6 +26,7 @@ import android.text.TextUtils;
|
||||
|
||||
import com.annimon.stream.function.Consumer;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
@ -45,6 +46,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessM
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.JazzIdenticonContactPhoto;
|
||||
import org.thoughtcrime.securesms.loki.RecipientAvatarModifiedEvent;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
@ -394,6 +396,7 @@ public class Recipient implements RecipientModifiedListener {
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
EventBus.getDefault().post(new RecipientAvatarModifiedEvent(this));
|
||||
}
|
||||
|
||||
public synchronized boolean isProfileSharing() {
|
||||
@ -469,7 +472,7 @@ public class Recipient implements RecipientModifiedListener {
|
||||
}
|
||||
|
||||
public synchronized @Nullable ContactPhoto getContactPhoto() {
|
||||
if (isLocalNumber) return null;
|
||||
if (isLocalNumber) return new ProfileContactPhoto(address, String.valueOf(TextSecurePreferences.getProfileAvatarId(context)));
|
||||
else if (isGroupRecipient() && groupAvatarId != null) return new GroupRecordContactPhoto(address, groupAvatarId);
|
||||
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
||||
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
||||
|
Loading…
x
Reference in New Issue
Block a user