diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index acc92c3c94..6133f2dee7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -33,6 +33,8 @@ import network.loki.messenger.databinding.ActivityWebrtcBinding import org.apache.commons.lang3.time.DurationFormatUtils import org.session.libsession.avatars.ProfileContactPhoto import org.session.libsession.messaging.contacts.Contact +import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsession.utilities.truncateIdForDisplay import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.dependencies.DatabaseComponent @@ -200,6 +202,16 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { } clipFloatingInsets() + + // set up the user avatar + TextSecurePreferences.getLocalNumber(this)?.let{ + val username = TextSecurePreferences.getProfileName(this) ?: truncateIdForDisplay(it) + binding.userAvatar.apply { + publicKey = it + displayName = username + update() + } + } } /** @@ -254,8 +266,10 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { else -> 0f } - remoteRecipient.animate().cancel() - remoteRecipient.animate().rotation(rotation).start() + userAvatar.animate().cancel() + userAvatar.animate().rotation(rotation).start() + contactAvatar.animate().cancel() + contactAvatar.animate().rotation(rotation).start() speakerPhoneButton.animate().cancel() speakerPhoneButton.animate().rotation(rotation).start() @@ -328,44 +342,20 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { launch { viewModel.recipient.collect { latestRecipient -> + binding.contactAvatar.recycle() + if (latestRecipient.recipient != null) { - val publicKey = latestRecipient.recipient.address.serialize() - val displayName = getUserDisplayName(publicKey) - supportActionBar?.title = displayName - val signalProfilePicture = latestRecipient.recipient.contactPhoto - val avatar = (signalProfilePicture as? ProfileContactPhoto)?.avatarObject - val sizeInPX = - resources.getDimensionPixelSize(R.dimen.extra_large_profile_picture_size) - binding.remoteRecipientName.text = displayName - if (signalProfilePicture != null && avatar != "0" && avatar != "") { - glide.clear(binding.remoteRecipient) - glide.load(signalProfilePicture) - .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) - .circleCrop() - .error( - AvatarPlaceholderGenerator.generate( - this@WebRtcCallActivity, - sizeInPX, - publicKey, - displayName - ) - ) - .into(binding.remoteRecipient) - } else { - glide.clear(binding.remoteRecipient) - glide.load( - AvatarPlaceholderGenerator.generate( - this@WebRtcCallActivity, - sizeInPX, - publicKey, - displayName - ) - ) - .diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop() - .into(binding.remoteRecipient) + val contactPublicKey = latestRecipient.recipient.address.serialize() + val contactDisplayName = getUserDisplayName(contactPublicKey) + supportActionBar?.title = contactDisplayName + binding.remoteRecipientName.text = contactDisplayName + + // sort out the contact's avatar + binding.contactAvatar.apply { + publicKey = contactPublicKey + displayName = contactDisplayName + update() } - } else { - glide.clear(binding.remoteRecipient) } } } @@ -400,22 +390,16 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.floatingRenderer.removeAllViews() binding.fullscreenRenderer.removeAllViews() - // the floating video inset (empty or not) should be shown - // the moment we have either of the video streams - val showFloatingContainer = state.userVideoEnabled || state.remoteVideoEnabled - binding.floatingRendererContainer.isVisible = showFloatingContainer - binding.swapViewIcon.isVisible = showFloatingContainer - // handle fullscreen video window if(state.showFullscreenVideo()){ viewModel.fullscreenRenderer?.let { surfaceView -> binding.fullscreenRenderer.addView(surfaceView) binding.fullscreenRenderer.isVisible = true - binding.remoteRecipient.isVisible = false + hideAvatar() } } else { binding.fullscreenRenderer.isVisible = false - binding.remoteRecipient.isVisible = true + showAvatar(state.swapped) } // handle floating video window @@ -429,6 +413,15 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.floatingRenderer.isVisible = false } + // the floating video inset (empty or not) should be shown + // the moment we have either of the video streams + val showFloatingContainer = state.userVideoEnabled || state.remoteVideoEnabled + binding.floatingRendererContainer.isVisible = showFloatingContainer + binding.swapViewIcon.isVisible = showFloatingContainer + + // make sure to default to the contact's avatar if the floating container is not visible + if (!showFloatingContainer) showAvatar(false) + // handle buttons binding.enableCameraButton.isSelected = state.userVideoEnabled } @@ -436,6 +429,20 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { } } + /** + * Shows the avatar image. + * If @showUserAvatar is true, the user's avatar is shown, otherwise the contact's avatar is shown. + */ + private fun showAvatar(showUserAvatar: Boolean) { + binding.userAvatar.isVisible = showUserAvatar + binding.contactAvatar.isVisible = !showUserAvatar + } + + private fun hideAvatar() { + binding.userAvatar.isVisible = false + binding.contactAvatar.isVisible = false + } + private fun getUserDisplayName(publicKey: String): String { val contact = DatabaseComponent.get(this).sessionContactDatabase().getContactWithSessionID(publicKey) 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 cddcc62485..846a94483f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt @@ -33,7 +33,6 @@ class ProfilePictureView @JvmOverloads constructor( var displayName: String? = null var additionalPublicKey: String? = null var additionalDisplayName: String? = null - var isLarge = false private val profilePicturesCache = mutableMapOf() private val unknownRecipientDrawable by lazy { ResourceContactPhoto(R.drawable.ic_profile_default) @@ -90,29 +89,25 @@ class ProfilePictureView @JvmOverloads constructor( fun update() { val publicKey = publicKey ?: return Log.w(TAG, "Could not find public key to update profile picture") val additionalPublicKey = additionalPublicKey + // if we have a multi avatar setup if (additionalPublicKey != null) { setProfilePictureIfNeeded(binding.doubleModeImageView1, publicKey, displayName) setProfilePictureIfNeeded(binding.doubleModeImageView2, additionalPublicKey, additionalDisplayName) binding.doubleModeImageViewContainer.visibility = View.VISIBLE - } else { + + // clear single image + glide.clear(binding.singleModeImageView) + binding.singleModeImageView.visibility = View.INVISIBLE + } else { // single image mode + setProfilePictureIfNeeded(binding.singleModeImageView, publicKey, displayName) + binding.singleModeImageView.visibility = View.VISIBLE + + // clear multi image glide.clear(binding.doubleModeImageView1) glide.clear(binding.doubleModeImageView2) binding.doubleModeImageViewContainer.visibility = View.INVISIBLE } - if (additionalPublicKey == null && !isLarge) { - setProfilePictureIfNeeded(binding.singleModeImageView, publicKey, displayName) - binding.singleModeImageView.visibility = View.VISIBLE - } else { - glide.clear(binding.singleModeImageView) - binding.singleModeImageView.visibility = View.INVISIBLE - } - if (additionalPublicKey == null && isLarge) { - setProfilePictureIfNeeded(binding.largeSingleModeImageView, publicKey, displayName) - binding.largeSingleModeImageView.visibility = View.VISIBLE - } else { - glide.clear(binding.largeSingleModeImageView) - binding.largeSingleModeImageView.visibility = View.INVISIBLE - } + } private fun setProfilePictureIfNeeded(imageView: ImageView, publicKey: String, displayName: String?) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt index bd38d0df86..fffed1baba 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt @@ -56,7 +56,6 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() { val threadRecipient = threadDb.getRecipientForThreadId(threadID) ?: return dismiss() with(binding) { profilePictureView.publicKey = publicKey - profilePictureView.isLarge = true profilePictureView.update(recipient) nameTextViewContainer.visibility = View.VISIBLE nameTextViewContainer.setOnClickListener { diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt index 67b716ce70..3d782b1c12 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -123,7 +123,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { view.apply { publicKey = hexEncodedPublicKey displayName = getDisplayName() - isLarge = true update() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt index 52cc0ad322..e2f8a9f21c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt @@ -61,6 +61,7 @@ import org.webrtc.SurfaceViewRenderer import java.nio.ByteBuffer import java.util.ArrayDeque import java.util.UUID +import kotlin.math.abs import org.thoughtcrime.securesms.webrtc.data.State as CallState class CallManager( @@ -718,7 +719,7 @@ class CallManager( // apply the rotation to the streams peerConnection?.setDeviceRotation(rotation) - remoteRotationSink?.rotation = rotation + remoteRotationSink?.rotation = abs(rotation) // abs as we never need the remote video to be inverted } fun handleWiredHeadsetChanged(present: Boolean) { diff --git a/app/src/main/res/drawable/profile_picture_view_large_background.xml b/app/src/main/res/drawable/profile_picture_view_background.xml similarity index 72% rename from app/src/main/res/drawable/profile_picture_view_large_background.xml rename to app/src/main/res/drawable/profile_picture_view_background.xml index 9b90660803..b8a7398a37 100644 --- a/app/src/main/res/drawable/profile_picture_view_large_background.xml +++ b/app/src/main/res/drawable/profile_picture_view_background.xml @@ -1,9 +1,8 @@ + android:shape="oval"> - \ No newline at end of file diff --git a/app/src/main/res/drawable/profile_picture_view_medium_background.xml b/app/src/main/res/drawable/profile_picture_view_medium_background.xml deleted file mode 100644 index 37c5ce3e74..0000000000 --- a/app/src/main/res/drawable/profile_picture_view_medium_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_webrtc.xml b/app/src/main/res/layout/activity_webrtc.xml index c285616a11..41ba0be86a 100644 --- a/app/src/main/res/layout/activity_webrtc.xml +++ b/app/src/main/res/layout/activity_webrtc.xml @@ -23,15 +23,27 @@ android:layout_height="wrap_content" android:layout_gravity="center"/> - + android:layout_height="@dimen/extra_large_profile_picture_size" + android:visibility="gone"/> + + - - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:adjustViewBounds="true" + android:background="@drawable/profile_picture_view_background" /> \ No newline at end of file