From 9419bafe93420993651b470bfa3b76d8b50047ac Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Fri, 18 Jun 2021 15:11:41 +1000 Subject: [PATCH] Add preliminary quote draft view --- .../conversation/v2/ConversationActivityV2.kt | 21 ++++--- .../conversation/v2/input_bar/InputBar.kt | 27 +++++++-- .../v2/input_bar/InputBarEditText.kt | 8 +-- .../conversation/v2/messages/QuoteView.kt | 43 ++++++++----- .../v2/messages/VisibleMessageContentView.kt | 2 +- .../v2/utilities/TextUtilities.kt | 17 ++++++ .../res/layout/activity_conversation_v2.xml | 2 +- app/src/main/res/layout/view_input_bar.xml | 5 ++ app/src/main/res/layout/view_quote.xml | 60 ++++++++++++++++--- 9 files changed, 138 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt 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 70b9ae9f54..e33204b787 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 @@ -22,7 +22,6 @@ import kotlinx.android.synthetic.main.view_input_bar_recording.* import kotlinx.android.synthetic.main.view_input_bar_recording.view.* import network.loki.messenger.R import org.session.libsession.messaging.mentions.MentionsManager -import org.session.libsession.messaging.mentions.MentionsManager.getMentionCandidates import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarDelegate @@ -155,15 +154,15 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe override fun inputBarHeightChanged(newValue: Int) { // Recycler view val recyclerViewLayoutParams = conversationRecyclerView.layoutParams as RelativeLayout.LayoutParams - recyclerViewLayoutParams.bottomMargin = newValue + inputBarAdditionalContentContainer.height + recyclerViewLayoutParams.bottomMargin = newValue + additionalContentContainer.height conversationRecyclerView.layoutParams = recyclerViewLayoutParams - // Input bar additional content container - val inputBarAdditionalContentContainerLayoutParams = inputBarAdditionalContentContainer.layoutParams as RelativeLayout.LayoutParams - inputBarAdditionalContentContainerLayoutParams.bottomMargin = newValue - inputBarAdditionalContentContainer.layoutParams = inputBarAdditionalContentContainerLayoutParams + // Additional content container + val additionalContentContainerLayoutParams = additionalContentContainer.layoutParams as RelativeLayout.LayoutParams + additionalContentContainerLayoutParams.bottomMargin = newValue + additionalContentContainer.layoutParams = additionalContentContainerLayoutParams // Attachment options val attachmentButtonHeight = inputBar.attachmentsButtonContainer.height - val bottomMargin = (newValue - attachmentButtonHeight) / 2 + val bottomMargin = (newValue - inputBar.inputBarAdditionalContentContainer.height - attachmentButtonHeight) / 2 val margin = toPx(8, resources) val attachmentOptionsContainerLayoutParams = attachmentOptionsContainer.layoutParams as RelativeLayout.LayoutParams attachmentOptionsContainerLayoutParams.bottomMargin = bottomMargin + attachmentButtonHeight + margin @@ -180,10 +179,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } private fun showMentionCandidates() { - inputBarAdditionalContentContainer.removeAllViews() + additionalContentContainer.removeAllViews() val mentionCandidatesView = MentionCandidatesView(this) mentionCandidatesView.glide = glide - inputBarAdditionalContentContainer.addView(mentionCandidatesView) + additionalContentContainer.addView(mentionCandidatesView) val mentionCandidates = MentionsManager.getMentionCandidates("", threadID, thread.isOpenGroupRecipient) this.mentionCandidatesView = mentionCandidatesView mentionCandidatesView.show(mentionCandidates, threadID) @@ -202,7 +201,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe animation.duration = 250L animation.addUpdateListener { animator -> mentionCandidatesView.alpha = animator.animatedValue as Float - if (animator.animatedFraction == 1.0f) { inputBarAdditionalContentContainer.removeAllViews() } + if (animator.animatedFraction == 1.0f) { additionalContentContainer.removeAllViews() } } animation.start() } @@ -269,7 +268,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe // `position` is the adapter position; not the visual position private fun handleSwipeToReply(message: MessageRecord, position: Int) { - + inputBar.draftQuote(message) } // `position` is the adapter position; not the visual position 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 596f5cf6cd..e8db8d69c9 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 @@ -9,6 +9,8 @@ import android.widget.RelativeLayout import androidx.core.view.isVisible import kotlinx.android.synthetic.main.view_input_bar.view.* import network.loki.messenger.R +import org.thoughtcrime.securesms.conversation.v2.messages.QuoteView +import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.loki.utilities.toDp import org.thoughtcrime.securesms.loki.utilities.toPx import kotlin.math.max @@ -48,6 +50,15 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate { } // endregion + // region General + private fun setHeight(newHeight: Int) { + val layoutParams = inputBarLinearLayout.layoutParams as LayoutParams + layoutParams.height = newHeight + inputBarLinearLayout.layoutParams = layoutParams + delegate?.inputBarHeightChanged(newHeight) + } + // endregion + // region Updating override fun inputBarEditTextContentChanged(text: CharSequence) { sendButton.isVisible = text.isNotEmpty() @@ -57,11 +68,8 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate { override fun inputBarEditTextHeightChanged(newValue: Int) { val vMargin = toDp(4, resources) - val layoutParams = inputBarLinearLayout.layoutParams as LayoutParams - val newHeight = max(newValue + 2 * vMargin, toPx(56, resources)) - layoutParams.height = newHeight - inputBarLinearLayout.layoutParams = layoutParams - delegate?.inputBarHeightChanged(newHeight) + val newHeight = max(newValue + 2 * vMargin + inputBarAdditionalContentContainer.height, toPx(56, resources)) + setHeight(newHeight) } private fun toggleAttachmentOptions() { @@ -71,6 +79,15 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate { private fun showVoiceMessageUI() { delegate?.showVoiceMessageUI() } + + fun draftQuote(message: MessageRecord) { + inputBarAdditionalContentContainer.removeAllViews() + val quoteView = QuoteView(context) + inputBarAdditionalContentContainer.addView(quoteView) + quoteView.bind("", "", null, message.recipient) + val newHeight = height + quoteView.getIntrinsicHeight() + setHeight(newHeight) + } // endregion } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt index 6a9f37cf27..16c4df83cf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt @@ -6,6 +6,7 @@ import android.text.StaticLayout import android.util.AttributeSet import android.widget.RelativeLayout import androidx.appcompat.widget.AppCompatEditText +import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities import org.thoughtcrime.securesms.loki.utilities.toPx import kotlin.math.max import kotlin.math.min @@ -24,12 +25,7 @@ class InputBarEditText : AppCompatEditText { override fun onTextChanged(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int) { super.onTextChanged(text, start, lengthBefore, lengthAfter) delegate?.inputBarEditTextContentChanged(text) - val builder = StaticLayout.Builder.obtain(text, 0, text.length, paint, width) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .setLineSpacing(0.0f, 1.0f) - .setIncludePad(false) - val layout = builder.build() - val height = layout.height.toFloat() + val height = TextUtilities.getIntrinsicHeight(text, paint, width).toFloat() val constrainedHeight = min(max(height, snMinHeight), snMaxHeight) if (constrainedHeight.roundToInt() == this.height) { return } val layoutParams = this.layoutParams as? RelativeLayout.LayoutParams ?: return 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 d13391113b..86be6b4255 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 @@ -1,36 +1,51 @@ package org.thoughtcrime.securesms.conversation.v2.messages import android.content.Context +import android.content.res.Resources import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout +import android.widget.RelativeLayout import kotlinx.android.synthetic.main.view_quote.view.* import network.loki.messenger.R +import org.session.libsession.utilities.recipients.Recipient +import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities import org.thoughtcrime.securesms.database.model.MessageRecord +import org.thoughtcrime.securesms.loki.utilities.toPx +import org.thoughtcrime.securesms.mms.SlideDeck class QuoteView : LinearLayout { + private val screenWidth by lazy { Resources.getSystem().displayMetrics.widthPixels } + + enum class Mode { Regular, Draft } // region Lifecycle - constructor(context: Context) : super(context) { - 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() } - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - setUpViewHierarchy() - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - setUpViewHierarchy() - } - - private fun setUpViewHierarchy() { + private fun initialize() { LayoutInflater.from(context).inflate(R.layout.view_quote, this) } // endregion + // region General + fun getIntrinsicHeight(): Int { + var result = 0 + val width = screenWidth + val author = quoteViewAuthorTextView.text + result += TextUtilities.getIntrinsicHeight(author, quoteViewAuthorTextView.paint, width) + val body = quoteViewBodyTextView.text + result += TextUtilities.getIntrinsicHeight(body, quoteViewBodyTextView.paint, width) + return result + } + // endregion + // region Updating - fun bind(message: MessageRecord) { - textView.text = "I'm a quote" + fun bind(authorPublicKey: String, body: String, attachments: SlideDeck?, thread: Recipient) { + val accentLineLayoutParams = quoteViewAccentLine.layoutParams as RelativeLayout.LayoutParams + accentLineLayoutParams.height = getIntrinsicHeight() + quoteViewAccentLine.layoutParams = accentLineLayoutParams } fun recycle() { 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 05edec29b7..b56e53ab8a 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 @@ -63,7 +63,7 @@ class VisibleMessageContentView : LinearLayout { mainContainer.addView(linkPreviewView) } else if (message is MmsMessageRecord && message.quote != null) { val quoteView = QuoteView(context) - quoteView.bind(message) + quoteView.bind(message.individualRecipient.address.toString(), "iuasfhiausfh", null, message.recipient) mainContainer.addView(quoteView) } else if (message is MmsMessageRecord && message.slideDeck.audioSlide != null) { val voiceMessageView = VoiceMessageView(context) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt new file mode 100644 index 0000000000..9bba134008 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt @@ -0,0 +1,17 @@ +package org.thoughtcrime.securesms.conversation.v2.utilities + +import android.text.Layout +import android.text.StaticLayout +import android.text.TextPaint + +object TextUtilities { + + fun getIntrinsicHeight(text: CharSequence, paint: TextPaint, width: Int): Int { + val builder = StaticLayout.Builder.obtain(text, 0, text.length, paint, width) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLineSpacing(0.0f, 1.0f) + .setIncludePad(false) + val layout = builder.build() + return layout.height + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_conversation_v2.xml b/app/src/main/res/layout/activity_conversation_v2.xml index 99493b6be5..d4ab70f531 100644 --- a/app/src/main/res/layout/activity_conversation_v2.xml +++ b/app/src/main/res/layout/activity_conversation_v2.xml @@ -19,7 +19,7 @@ android:layout_alignParentBottom="true" /> + + diff --git a/app/src/main/res/layout/view_quote.xml b/app/src/main/res/layout/view_quote.xml index e54f8e930c..eb7e28aa15 100644 --- a/app/src/main/res/layout/view_quote.xml +++ b/app/src/main/res/layout/view_quote.xml @@ -1,16 +1,58 @@ - + android:background="@color/input_bar_background" + android:gravity="center_vertical"> - + + + + + android:layout_marginStart="12dp" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:orientation="vertical"> - \ No newline at end of file + + + + + + + + + \ No newline at end of file