mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-18 05:57:44 +00:00
Add preliminary quote draft view
This commit is contained in:
parent
be158eccc1
commit
9419bafe93
@ -22,7 +22,6 @@ import kotlinx.android.synthetic.main.view_input_bar_recording.*
|
|||||||
import kotlinx.android.synthetic.main.view_input_bar_recording.view.*
|
import kotlinx.android.synthetic.main.view_input_bar_recording.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.messaging.mentions.MentionsManager
|
import org.session.libsession.messaging.mentions.MentionsManager
|
||||||
import org.session.libsession.messaging.mentions.MentionsManager.getMentionCandidates
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton
|
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton
|
||||||
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarDelegate
|
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarDelegate
|
||||||
@ -155,15 +154,15 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
override fun inputBarHeightChanged(newValue: Int) {
|
override fun inputBarHeightChanged(newValue: Int) {
|
||||||
// Recycler view
|
// Recycler view
|
||||||
val recyclerViewLayoutParams = conversationRecyclerView.layoutParams as RelativeLayout.LayoutParams
|
val recyclerViewLayoutParams = conversationRecyclerView.layoutParams as RelativeLayout.LayoutParams
|
||||||
recyclerViewLayoutParams.bottomMargin = newValue + inputBarAdditionalContentContainer.height
|
recyclerViewLayoutParams.bottomMargin = newValue + additionalContentContainer.height
|
||||||
conversationRecyclerView.layoutParams = recyclerViewLayoutParams
|
conversationRecyclerView.layoutParams = recyclerViewLayoutParams
|
||||||
// Input bar additional content container
|
// Additional content container
|
||||||
val inputBarAdditionalContentContainerLayoutParams = inputBarAdditionalContentContainer.layoutParams as RelativeLayout.LayoutParams
|
val additionalContentContainerLayoutParams = additionalContentContainer.layoutParams as RelativeLayout.LayoutParams
|
||||||
inputBarAdditionalContentContainerLayoutParams.bottomMargin = newValue
|
additionalContentContainerLayoutParams.bottomMargin = newValue
|
||||||
inputBarAdditionalContentContainer.layoutParams = inputBarAdditionalContentContainerLayoutParams
|
additionalContentContainer.layoutParams = additionalContentContainerLayoutParams
|
||||||
// Attachment options
|
// Attachment options
|
||||||
val attachmentButtonHeight = inputBar.attachmentsButtonContainer.height
|
val attachmentButtonHeight = inputBar.attachmentsButtonContainer.height
|
||||||
val bottomMargin = (newValue - attachmentButtonHeight) / 2
|
val bottomMargin = (newValue - inputBar.inputBarAdditionalContentContainer.height - attachmentButtonHeight) / 2
|
||||||
val margin = toPx(8, resources)
|
val margin = toPx(8, resources)
|
||||||
val attachmentOptionsContainerLayoutParams = attachmentOptionsContainer.layoutParams as RelativeLayout.LayoutParams
|
val attachmentOptionsContainerLayoutParams = attachmentOptionsContainer.layoutParams as RelativeLayout.LayoutParams
|
||||||
attachmentOptionsContainerLayoutParams.bottomMargin = bottomMargin + attachmentButtonHeight + margin
|
attachmentOptionsContainerLayoutParams.bottomMargin = bottomMargin + attachmentButtonHeight + margin
|
||||||
@ -180,10 +179,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showMentionCandidates() {
|
private fun showMentionCandidates() {
|
||||||
inputBarAdditionalContentContainer.removeAllViews()
|
additionalContentContainer.removeAllViews()
|
||||||
val mentionCandidatesView = MentionCandidatesView(this)
|
val mentionCandidatesView = MentionCandidatesView(this)
|
||||||
mentionCandidatesView.glide = glide
|
mentionCandidatesView.glide = glide
|
||||||
inputBarAdditionalContentContainer.addView(mentionCandidatesView)
|
additionalContentContainer.addView(mentionCandidatesView)
|
||||||
val mentionCandidates = MentionsManager.getMentionCandidates("", threadID, thread.isOpenGroupRecipient)
|
val mentionCandidates = MentionsManager.getMentionCandidates("", threadID, thread.isOpenGroupRecipient)
|
||||||
this.mentionCandidatesView = mentionCandidatesView
|
this.mentionCandidatesView = mentionCandidatesView
|
||||||
mentionCandidatesView.show(mentionCandidates, threadID)
|
mentionCandidatesView.show(mentionCandidates, threadID)
|
||||||
@ -202,7 +201,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
animation.duration = 250L
|
animation.duration = 250L
|
||||||
animation.addUpdateListener { animator ->
|
animation.addUpdateListener { animator ->
|
||||||
mentionCandidatesView.alpha = animator.animatedValue as Float
|
mentionCandidatesView.alpha = animator.animatedValue as Float
|
||||||
if (animator.animatedFraction == 1.0f) { inputBarAdditionalContentContainer.removeAllViews() }
|
if (animator.animatedFraction == 1.0f) { additionalContentContainer.removeAllViews() }
|
||||||
}
|
}
|
||||||
animation.start()
|
animation.start()
|
||||||
}
|
}
|
||||||
@ -269,7 +268,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
// `position` is the adapter position; not the visual position
|
// `position` is the adapter position; not the visual position
|
||||||
private fun handleSwipeToReply(message: MessageRecord, position: Int) {
|
private fun handleSwipeToReply(message: MessageRecord, position: Int) {
|
||||||
|
inputBar.draftQuote(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// `position` is the adapter position; not the visual position
|
// `position` is the adapter position; not the visual position
|
||||||
|
@ -9,6 +9,8 @@ import android.widget.RelativeLayout
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import kotlinx.android.synthetic.main.view_input_bar.view.*
|
import kotlinx.android.synthetic.main.view_input_bar.view.*
|
||||||
import network.loki.messenger.R
|
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.toDp
|
||||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
@ -48,6 +50,15 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate {
|
|||||||
}
|
}
|
||||||
// endregion
|
// 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
|
// region Updating
|
||||||
override fun inputBarEditTextContentChanged(text: CharSequence) {
|
override fun inputBarEditTextContentChanged(text: CharSequence) {
|
||||||
sendButton.isVisible = text.isNotEmpty()
|
sendButton.isVisible = text.isNotEmpty()
|
||||||
@ -57,11 +68,8 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate {
|
|||||||
|
|
||||||
override fun inputBarEditTextHeightChanged(newValue: Int) {
|
override fun inputBarEditTextHeightChanged(newValue: Int) {
|
||||||
val vMargin = toDp(4, resources)
|
val vMargin = toDp(4, resources)
|
||||||
val layoutParams = inputBarLinearLayout.layoutParams as LayoutParams
|
val newHeight = max(newValue + 2 * vMargin + inputBarAdditionalContentContainer.height, toPx(56, resources))
|
||||||
val newHeight = max(newValue + 2 * vMargin, toPx(56, resources))
|
setHeight(newHeight)
|
||||||
layoutParams.height = newHeight
|
|
||||||
inputBarLinearLayout.layoutParams = layoutParams
|
|
||||||
delegate?.inputBarHeightChanged(newHeight)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleAttachmentOptions() {
|
private fun toggleAttachmentOptions() {
|
||||||
@ -71,6 +79,15 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate {
|
|||||||
private fun showVoiceMessageUI() {
|
private fun showVoiceMessageUI() {
|
||||||
delegate?.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
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import android.text.StaticLayout
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.appcompat.widget.AppCompatEditText
|
import androidx.appcompat.widget.AppCompatEditText
|
||||||
|
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities
|
||||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@ -24,12 +25,7 @@ class InputBarEditText : AppCompatEditText {
|
|||||||
override fun onTextChanged(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int) {
|
override fun onTextChanged(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int) {
|
||||||
super.onTextChanged(text, start, lengthBefore, lengthAfter)
|
super.onTextChanged(text, start, lengthBefore, lengthAfter)
|
||||||
delegate?.inputBarEditTextContentChanged(text)
|
delegate?.inputBarEditTextContentChanged(text)
|
||||||
val builder = StaticLayout.Builder.obtain(text, 0, text.length, paint, width)
|
val height = TextUtilities.getIntrinsicHeight(text, paint, width).toFloat()
|
||||||
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
|
|
||||||
.setLineSpacing(0.0f, 1.0f)
|
|
||||||
.setIncludePad(false)
|
|
||||||
val layout = builder.build()
|
|
||||||
val height = layout.height.toFloat()
|
|
||||||
val constrainedHeight = min(max(height, snMinHeight), snMaxHeight)
|
val constrainedHeight = min(max(height, snMinHeight), snMaxHeight)
|
||||||
if (constrainedHeight.roundToInt() == this.height) { return }
|
if (constrainedHeight.roundToInt() == this.height) { return }
|
||||||
val layoutParams = this.layoutParams as? RelativeLayout.LayoutParams ?: return
|
val layoutParams = this.layoutParams as? RelativeLayout.LayoutParams ?: return
|
||||||
|
@ -1,36 +1,51 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.messages
|
package org.thoughtcrime.securesms.conversation.v2.messages
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.RelativeLayout
|
||||||
import kotlinx.android.synthetic.main.view_quote.view.*
|
import kotlinx.android.synthetic.main.view_quote.view.*
|
||||||
import network.loki.messenger.R
|
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.database.model.MessageRecord
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||||
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
|
|
||||||
class QuoteView : LinearLayout {
|
class QuoteView : LinearLayout {
|
||||||
|
private val screenWidth by lazy { Resources.getSystem().displayMetrics.widthPixels }
|
||||||
|
|
||||||
|
enum class Mode { Regular, Draft }
|
||||||
|
|
||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
constructor(context: Context) : super(context) {
|
constructor(context: Context) : super(context) { initialize() }
|
||||||
setUpViewHierarchy()
|
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) {
|
private fun initialize() {
|
||||||
setUpViewHierarchy()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
|
||||||
setUpViewHierarchy()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpViewHierarchy() {
|
|
||||||
LayoutInflater.from(context).inflate(R.layout.view_quote, this)
|
LayoutInflater.from(context).inflate(R.layout.view_quote, this)
|
||||||
}
|
}
|
||||||
// endregion
|
// 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
|
// region Updating
|
||||||
fun bind(message: MessageRecord) {
|
fun bind(authorPublicKey: String, body: String, attachments: SlideDeck?, thread: Recipient) {
|
||||||
textView.text = "I'm a quote"
|
val accentLineLayoutParams = quoteViewAccentLine.layoutParams as RelativeLayout.LayoutParams
|
||||||
|
accentLineLayoutParams.height = getIntrinsicHeight()
|
||||||
|
quoteViewAccentLine.layoutParams = accentLineLayoutParams
|
||||||
}
|
}
|
||||||
|
|
||||||
fun recycle() {
|
fun recycle() {
|
||||||
|
@ -63,7 +63,7 @@ class VisibleMessageContentView : LinearLayout {
|
|||||||
mainContainer.addView(linkPreviewView)
|
mainContainer.addView(linkPreviewView)
|
||||||
} else if (message is MmsMessageRecord && message.quote != null) {
|
} else if (message is MmsMessageRecord && message.quote != null) {
|
||||||
val quoteView = QuoteView(context)
|
val quoteView = QuoteView(context)
|
||||||
quoteView.bind(message)
|
quoteView.bind(message.individualRecipient.address.toString(), "iuasfhiausfh", null, message.recipient)
|
||||||
mainContainer.addView(quoteView)
|
mainContainer.addView(quoteView)
|
||||||
} else if (message is MmsMessageRecord && message.slideDeck.audioSlide != null) {
|
} else if (message is MmsMessageRecord && message.slideDeck.audioSlide != null) {
|
||||||
val voiceMessageView = VoiceMessageView(context)
|
val voiceMessageView = VoiceMessageView(context)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@
|
|||||||
android:layout_alignParentBottom="true" />
|
android:layout_alignParentBottom="true" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/inputBarAdditionalContentContainer"
|
android:id="@+id/additionalContentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
android:layout_height="1px"
|
android:layout_height="1px"
|
||||||
android:background="@color/separator" />
|
android:background="@color/separator" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/inputBarAdditionalContentContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
@ -1,16 +1,58 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:background="@color/input_bar_background"
|
||||||
android:gravity="center">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<TextView
|
<View
|
||||||
android:id="@+id/textView"
|
android:id="@+id/quoteViewAccentLine"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="@dimen/accent_line_thickness"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:background="@color/text" />
|
||||||
|
|
||||||
|
<!-- The start margin below is the accent line thickness (4 dp) + small spacing (8 dp) -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:layout_marginStart="12dp"
|
||||||
android:textColor="@color/text" />
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
</LinearLayout>
|
<TextView
|
||||||
|
android:id="@+id/quoteViewAuthorTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Spiderman"
|
||||||
|
android:textSize="@dimen/small_font_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/quoteViewBodyTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Yo, I need your help here!"
|
||||||
|
android:textSize="@dimen/small_font_size"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/ic_x_28" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
Loading…
x
Reference in New Issue
Block a user