From 123cd6d4865b8a3a53342b5c8ffad2162bec1638 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Fri, 18 Jun 2021 15:54:24 +1000 Subject: [PATCH] Handle text only quote drafts --- .../conversation/v2/ConversationActivityV2.kt | 100 +++++++++--------- .../conversation/v2/input_bar/InputBar.kt | 2 +- .../v2/input_bar/InputBarRecordingView.kt | 6 +- .../conversation/v2/messages/QuoteView.kt | 41 +++++-- .../v2/messages/VisibleMessageContentView.kt | 18 +--- .../v2/messages/VisibleMessageView.kt | 14 +-- app/src/main/res/layout/view_quote.xml | 13 ++- .../libsession/messaging/contacts/Contact.kt | 6 +- 8 files changed, 101 insertions(+), 99 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index e33204b787..3a6742740f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -38,7 +38,7 @@ import kotlin.math.roundToInt import kotlin.math.sqrt class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate, InputBarRecordingViewDelegate { - private val lockViewHitMargin by lazy { toPx(40, resources) } + private val screenWidth = Resources.getSystem().displayMetrics.widthPixels private var threadID: Long = -1 private var actionMode: ActionMode? = null private var isLockViewExpanded = false @@ -72,9 +72,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } private val glide by lazy { GlideApp.with(this) } - - private val screenWidth by lazy { Resources.getSystem().displayMetrics.widthPixels } - + private val lockViewHitMargin by lazy { toPx(40, resources) } private val gifButton by lazy { InputBarButton(this, R.drawable.ic_gif_white_24dp, hasOpaqueBackground = true, isGIFButton = true) } private val documentButton by lazy { InputBarButton(this, R.drawable.ic_document_small_dark, hasOpaqueBackground = true) } private val libraryButton by lazy { InputBarButton(this, R.drawable.ic_baseline_photo_library_24, hasOpaqueBackground = true) } @@ -150,7 +148,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } // endregion - // region Updating + // region Updating & Animation override fun inputBarHeightChanged(newValue: Int) { // Recycler view val recyclerViewLayoutParams = conversationRecyclerView.layoutParams as RelativeLayout.LayoutParams @@ -170,7 +168,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } override fun inputBarEditTextContentChanged(newContent: CharSequence) { - // TODO: Work this out further + // TODO: Implement the full mention show/hide logic if (newContent.contains("@")) { showMentionCandidates() } else { @@ -235,7 +233,41 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe animation.start() } - override fun handleInputBarRecordingViewHidden() { + private fun expandVoiceMessageLockView() { + val animation = ValueAnimator.ofObject(FloatEvaluator(), lockView.scaleX, 1.10f) + animation.duration = 250L + animation.addUpdateListener { animator -> + lockView.scaleX = animator.animatedValue as Float + lockView.scaleY = animator.animatedValue as Float + } + animation.start() + } + + private fun collapseVoiceMessageLockView() { + val animation = ValueAnimator.ofObject(FloatEvaluator(), lockView.scaleX, 1.0f) + animation.duration = 250L + animation.addUpdateListener { animator -> + lockView.scaleX = animator.animatedValue as Float + lockView.scaleY = animator.animatedValue as Float + } + animation.start() + } + + private fun hideVoiceMessageUI() { + val chevronImageView = inputBarRecordingView.inputBarChevronImageView + val slideToCancelTextView = inputBarRecordingView.inputBarSlideToCancelTextView + listOf( chevronImageView, slideToCancelTextView ).forEach { view -> + val animation = ValueAnimator.ofObject(FloatEvaluator(), view.translationX, 0.0f) + animation.duration = 250L + animation.addUpdateListener { animator -> + view.translationX = animator.animatedValue as Float + } + animation.start() + } + inputBarRecordingView.hide() + } + + override fun handleVoiceMessageUIHidden() { inputBar.alpha = 1.0f val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f) animation.duration = 250L @@ -311,69 +343,35 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } if (isValidLockViewLocation(event.rawX.roundToInt(), event.rawY.roundToInt())) { if (!isLockViewExpanded) { - expandLockView() + expandVoiceMessageLockView() isLockViewExpanded = true } } else { if (isLockViewExpanded) { - collapseLockView() + collapseVoiceMessageLockView() isLockViewExpanded = false } } } - private fun isValidLockViewLocation(x: Int, y: Int): Boolean { - val lockViewLocation = IntArray(2) { 0 } - lockView.getLocationOnScreen(lockViewLocation) - val hitRect = Rect(lockViewLocation[0] - lockViewHitMargin, 0, - lockViewLocation[0] + lockView.width + lockViewHitMargin, lockViewLocation[1] + lockView.height) - return hitRect.contains(x, y) - } - - private fun expandLockView() { - val animation = ValueAnimator.ofObject(FloatEvaluator(), lockView.scaleX, 1.10f) - animation.duration = 250L - animation.addUpdateListener { animator -> - lockView.scaleX = animator.animatedValue as Float - lockView.scaleY = animator.animatedValue as Float - } - animation.start() - } - - private fun collapseLockView() { - val animation = ValueAnimator.ofObject(FloatEvaluator(), lockView.scaleX, 1.0f) - animation.duration = 250L - animation.addUpdateListener { animator -> - lockView.scaleX = animator.animatedValue as Float - lockView.scaleY = animator.animatedValue as Float - } - animation.start() - } - override fun onMicrophoneButtonCancel(event: MotionEvent) { - resetVoiceMessageUI() + hideVoiceMessageUI() } override fun onMicrophoneButtonUp(event: MotionEvent) { if (isValidLockViewLocation(event.rawX.roundToInt(), event.rawY.roundToInt())) { inputBarRecordingView.lock() } else { - resetVoiceMessageUI() + hideVoiceMessageUI() } } - private fun resetVoiceMessageUI() { - val chevronImageView = inputBarRecordingView.inputBarChevronImageView - val slideToCancelTextView = inputBarRecordingView.inputBarSlideToCancelTextView - listOf( chevronImageView, slideToCancelTextView ).forEach { view -> - val animation = ValueAnimator.ofObject(FloatEvaluator(), view.translationX, 0.0f) - animation.duration = 250L - animation.addUpdateListener { animator -> - view.translationX = animator.animatedValue as Float - } - animation.start() - } - inputBarRecordingView.hide() + private fun isValidLockViewLocation(x: Int, y: Int): Boolean { + val lockViewLocation = IntArray(2) { 0 } + lockView.getLocationOnScreen(lockViewLocation) + val hitRect = Rect(lockViewLocation[0] - lockViewHitMargin, 0, + lockViewLocation[0] + lockView.width + lockViewHitMargin, lockViewLocation[1] + lockView.height) + return hitRect.contains(x, y) } // endregion } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt index e8db8d69c9..cd76e4ce5e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt @@ -84,7 +84,7 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate { inputBarAdditionalContentContainer.removeAllViews() val quoteView = QuoteView(context) inputBarAdditionalContentContainer.addView(quoteView) - quoteView.bind("", "", null, message.recipient) + quoteView.bind(message.individualRecipient.address.toString(), message.body, null, message.recipient) val newHeight = height + quoteView.getIntrinsicHeight() setHeight(newHeight) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt index 66fc65446e..a4da17434f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt @@ -7,7 +7,6 @@ import android.content.Context import android.os.Handler import android.os.Looper import android.util.AttributeSet -import android.util.Log import android.view.LayoutInflater import android.widget.RelativeLayout import androidx.core.content.res.ResourcesCompat @@ -19,7 +18,6 @@ import org.thoughtcrime.securesms.loki.utilities.disableClipping import org.thoughtcrime.securesms.loki.utilities.toPx import org.thoughtcrime.securesms.util.DateUtils import java.util.* -import kotlin.math.roundToLong class InputBarRecordingView : RelativeLayout { private var startTimestamp = 0L @@ -71,7 +69,7 @@ class InputBarRecordingView : RelativeLayout { } } animation.start() - delegate?.handleInputBarRecordingViewHidden() + delegate?.handleVoiceMessageUIHidden() } private fun animateDotView() { @@ -141,5 +139,5 @@ class InputBarRecordingView : RelativeLayout { interface InputBarRecordingViewDelegate { - fun handleInputBarRecordingViewHidden() + fun handleVoiceMessageUIHidden() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt index 86be6b4255..4c11cf6826 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt @@ -6,16 +6,22 @@ import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.RelativeLayout +import androidx.core.view.isVisible import kotlinx.android.synthetic.main.view_quote.view.* import network.loki.messenger.R +import org.session.libsession.messaging.contacts.Contact import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities +import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.loki.utilities.toPx import org.thoughtcrime.securesms.mms.SlideDeck +import kotlin.math.max +import kotlin.math.min class QuoteView : LinearLayout { private val screenWidth by lazy { Resources.getSystem().displayMetrics.widthPixels } + private val vPadding by lazy { toPx(6, resources) } enum class Mode { Regular, Draft } @@ -30,26 +36,43 @@ class QuoteView : LinearLayout { // endregion // region General - fun getIntrinsicHeight(): Int { + fun getIntrinsicContentHeight(): Int { var result = 0 val width = screenWidth val author = quoteViewAuthorTextView.text - result += TextUtilities.getIntrinsicHeight(author, quoteViewAuthorTextView.paint, width) + val authorTextViewIntrinsicHeight = TextUtilities.getIntrinsicHeight(author, quoteViewAuthorTextView.paint, width) + result += authorTextViewIntrinsicHeight val body = quoteViewBodyTextView.text - result += TextUtilities.getIntrinsicHeight(body, quoteViewBodyTextView.paint, width) - return result + val bodyTextViewIntrinsicHeight = TextUtilities.getIntrinsicHeight(body, quoteViewBodyTextView.paint, width) + result += bodyTextViewIntrinsicHeight + if (!quoteViewAuthorTextView.isVisible) { + return min(max(result, toPx(32, resources)), toPx(54, resources)) + } else { + return min(result, toPx(54, resources) + authorTextViewIntrinsicHeight) + } + } + + fun getIntrinsicHeight(): Int { + return getIntrinsicContentHeight() + 2 * vPadding } // endregion // region Updating fun bind(authorPublicKey: String, body: String, attachments: SlideDeck?, thread: Recipient) { + val contactDB = DatabaseFactory.getSessionContactDatabase(context) + // Author + if (thread.isGroupRecipient) { + val author = contactDB.getContactWithSessionID(authorPublicKey) + val authorDisplayName = author?.displayName(Contact.contextForRecipient(thread)) ?: authorPublicKey + quoteViewAuthorTextView.text = authorDisplayName + } + quoteViewAuthorTextView.isVisible = thread.isGroupRecipient + // Body + quoteViewBodyTextView.text = body + // Accent line val accentLineLayoutParams = quoteViewAccentLine.layoutParams as RelativeLayout.LayoutParams - accentLineLayoutParams.height = getIntrinsicHeight() + accentLineLayoutParams.height = getIntrinsicContentHeight() quoteViewAccentLine.layoutParams = accentLineLayoutParams } - - fun recycle() { - // TODO: Implement - } // endregion } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt index b56e53ab8a..cce23aa7c5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt @@ -11,8 +11,6 @@ import androidx.annotation.DrawableRes import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeCompat -import androidx.core.view.setMargins -import androidx.core.view.setPadding import kotlinx.android.synthetic.main.view_visible_message_content.view.* import network.loki.messenger.R import org.session.libsession.utilities.ThemeUtil @@ -29,19 +27,11 @@ class VisibleMessageContentView : LinearLayout { // TODO: Large emojis // region Lifecycle - constructor(context: Context) : super(context) { - setUpViewHierarchy() - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - setUpViewHierarchy() - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - setUpViewHierarchy() - } + constructor(context: Context) : super(context) { initialize() } + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() } + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() } - private fun setUpViewHierarchy() { + private fun initialize() { LayoutInflater.from(context).inflate(R.layout.view_visible_message_content, this) } // endregion diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt index 1b26830350..c1d7006a33 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt @@ -53,17 +53,9 @@ class VisibleMessageView : LinearLayout { } // region Lifecycle - constructor(context: Context) : super(context) { - initialize() - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - initialize() - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - initialize() - } + constructor(context: Context) : super(context) { initialize() } + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() } + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() } private fun initialize() { LayoutInflater.from(context).inflate(R.layout.view_visible_message, this) diff --git a/app/src/main/res/layout/view_quote.xml b/app/src/main/res/layout/view_quote.xml index eb7e28aa15..49673ec0d0 100644 --- a/app/src/main/res/layout/view_quote.xml +++ b/app/src/main/res/layout/view_quote.xml @@ -3,7 +3,10 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto" android:background="@color/input_bar_background" + android:paddingHorizontal="@dimen/medium_spacing" + android:paddingVertical="6dp" android:gravity="center_vertical"> - + @@ -50,9 +54,10 @@ + android:src="@drawable/ic_close_white_48dp" + app:tint="@color/text" /> \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/contacts/Contact.kt b/libsession/src/main/java/org/session/libsession/messaging/contacts/Contact.kt index 9eb34841a3..bede188329 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/contacts/Contact.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/contacts/Contact.kt @@ -77,11 +77,7 @@ class Contact(val sessionID: String) { companion object { fun contextForRecipient(recipient: Recipient): ContactContext { - return if (recipient.isOpenGroupRecipient) { - ContactContext.OPEN_GROUP - } else { - ContactContext.REGULAR - } + return if (recipient.isOpenGroupRecipient) ContactContext.OPEN_GROUP else ContactContext.REGULAR } } } \ No newline at end of file