mirror of
https://github.com/oxen-io/session-android.git
synced 2025-03-13 21:30:56 +00:00
Handle text only quote drafts
This commit is contained in:
parent
9419bafe93
commit
123cd6d486
@ -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,17 +343,29 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMicrophoneButtonCancel(event: MotionEvent) {
|
||||
hideVoiceMessageUI()
|
||||
}
|
||||
|
||||
override fun onMicrophoneButtonUp(event: MotionEvent) {
|
||||
if (isValidLockViewLocation(event.rawX.roundToInt(), event.rawY.roundToInt())) {
|
||||
inputBarRecordingView.lock()
|
||||
} else {
|
||||
hideVoiceMessageUI()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidLockViewLocation(x: Int, y: Int): Boolean {
|
||||
val lockViewLocation = IntArray(2) { 0 }
|
||||
lockView.getLocationOnScreen(lockViewLocation)
|
||||
@ -329,51 +373,5 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
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()
|
||||
}
|
||||
|
||||
override fun onMicrophoneButtonUp(event: MotionEvent) {
|
||||
if (isValidLockViewLocation(event.rawX.roundToInt(), event.rawY.roundToInt())) {
|
||||
inputBarRecordingView.lock()
|
||||
} else {
|
||||
resetVoiceMessageUI()
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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) : 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_visible_message_content, this)
|
||||
}
|
||||
// endregion
|
||||
|
@ -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)
|
||||
|
@ -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">
|
||||
|
||||
<View
|
||||
@ -14,12 +17,13 @@
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@color/text" />
|
||||
|
||||
<!-- The start margin below is the accent line thickness (4 dp) + small spacing (8 dp) -->
|
||||
<!-- The start margin below is the accent line thickness (4 dp) + 12 dp -->
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:orientation="vertical">
|
||||
@ -50,9 +54,10 @@
|
||||
<ImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:padding="8dp"
|
||||
android:padding="6dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/ic_x_28" />
|
||||
android:src="@drawable/ic_close_white_48dp"
|
||||
app:tint="@color/text" />
|
||||
|
||||
</RelativeLayout>
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user