kopia lustrzana https://github.com/ryukoposting/Signal-Android
219 wiersze
6.6 KiB
Kotlin
219 wiersze
6.6 KiB
Kotlin
package org.thoughtcrime.securesms.stories
|
|
|
|
import android.content.Context
|
|
import android.graphics.Typeface
|
|
import android.graphics.drawable.Drawable
|
|
import android.util.AttributeSet
|
|
import android.util.TypedValue
|
|
import android.view.View
|
|
import android.widget.ImageView
|
|
import androidx.annotation.ColorInt
|
|
import androidx.annotation.Px
|
|
import androidx.constraintlayout.widget.ConstraintLayout
|
|
import androidx.core.graphics.ColorUtils
|
|
import androidx.core.view.doOnNextLayout
|
|
import androidx.core.view.isVisible
|
|
import org.thoughtcrime.securesms.R
|
|
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
|
import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost
|
|
import org.thoughtcrime.securesms.fonts.TextFont
|
|
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
|
|
import org.thoughtcrime.securesms.mediasend.v2.text.TextAlignment
|
|
import org.thoughtcrime.securesms.mediasend.v2.text.TextStoryPostCreationState
|
|
import org.thoughtcrime.securesms.mediasend.v2.text.TextStoryScale
|
|
import org.thoughtcrime.securesms.mediasend.v2.text.TextStoryTextWatcher
|
|
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture
|
|
import org.thoughtcrime.securesms.util.visible
|
|
import java.util.Locale
|
|
|
|
class StoryTextPostView @JvmOverloads constructor(
|
|
context: Context,
|
|
attrs: AttributeSet? = null,
|
|
defStyleAttr: Int = 0
|
|
) : ConstraintLayout(context, attrs, defStyleAttr) {
|
|
|
|
init {
|
|
inflate(context, R.layout.stories_text_post_view, this)
|
|
}
|
|
|
|
private var textAlignment: TextAlignment? = null
|
|
private val backgroundView: ImageView = findViewById(R.id.text_story_post_background)
|
|
private val textView: StoryTextView = findViewById(R.id.text_story_post_text)
|
|
private val linkPreviewView: StoryLinkPreviewView = findViewById(R.id.text_story_post_link_preview)
|
|
|
|
private var isPlaceholder: Boolean = true
|
|
|
|
init {
|
|
TextStoryTextWatcher.install(textView)
|
|
}
|
|
|
|
fun showCloseButton() {
|
|
linkPreviewView.setCanClose(true)
|
|
}
|
|
|
|
fun hideCloseButton() {
|
|
linkPreviewView.setCanClose(false)
|
|
}
|
|
|
|
fun setTypeface(typeface: Typeface) {
|
|
textView.typeface = typeface
|
|
}
|
|
|
|
private fun setPostBackground(drawable: Drawable) {
|
|
backgroundView.setImageDrawable(drawable)
|
|
}
|
|
|
|
private fun setTextColor(@ColorInt color: Int, isPlaceholder: Boolean) {
|
|
if (isPlaceholder) {
|
|
textView.setTextColor(ColorUtils.setAlphaComponent(color, 0x99))
|
|
} else {
|
|
textView.setTextColor(color)
|
|
}
|
|
}
|
|
|
|
private fun setText(text: CharSequence, isPlaceholder: Boolean) {
|
|
this.isPlaceholder = isPlaceholder
|
|
textView.text = text
|
|
}
|
|
|
|
private fun setTextSize(@Px textSize: Float) {
|
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
|
|
}
|
|
|
|
private fun setTextGravity(textAlignment: TextAlignment) {
|
|
textView.gravity = textAlignment.gravity
|
|
}
|
|
|
|
private fun setTextScale(scalePercent: Int) {
|
|
val scale = TextStoryScale.convertToScale(scalePercent)
|
|
textView.scaleX = scale
|
|
textView.scaleY = scale
|
|
}
|
|
|
|
private fun setTextVisible(visible: Boolean) {
|
|
textView.visible = visible
|
|
}
|
|
|
|
private fun setTextBackgroundColor(@ColorInt color: Int) {
|
|
textView.setWrappedBackgroundColor(color)
|
|
}
|
|
|
|
fun bindFromCreationState(state: TextStoryPostCreationState) {
|
|
textAlignment = state.textAlignment
|
|
|
|
setPostBackground(state.backgroundColor.chatBubbleMask)
|
|
setText(
|
|
state.body.ifEmpty {
|
|
context.getString(R.string.TextStoryPostCreationFragment__tap_to_add_text)
|
|
}.let {
|
|
if (state.textFont.isAllCaps) {
|
|
it.toString().uppercase(Locale.getDefault())
|
|
} else {
|
|
it
|
|
}
|
|
},
|
|
state.body.isEmpty()
|
|
)
|
|
|
|
setTextColor(state.textForegroundColor, state.body.isEmpty())
|
|
setTextBackgroundColor(state.textBackgroundColor)
|
|
setTextGravity(state.textAlignment)
|
|
setTextScale(state.textScale)
|
|
|
|
postAdjustLinkPreviewTranslationY()
|
|
}
|
|
|
|
fun bindFromStoryTextPost(storyTextPost: StoryTextPost) {
|
|
visible = true
|
|
linkPreviewView.visible = false
|
|
|
|
textAlignment = TextAlignment.CENTER
|
|
|
|
val font = TextFont.fromStyle(storyTextPost.style)
|
|
setPostBackground(ChatColors.forChatColor(ChatColors.Id.NotSet, storyTextPost.background).chatBubbleMask)
|
|
|
|
if (font.isAllCaps) {
|
|
setText(storyTextPost.body.uppercase(Locale.getDefault()), false)
|
|
} else {
|
|
setText(storyTextPost.body, false)
|
|
}
|
|
|
|
setTextColor(storyTextPost.textForegroundColor, false)
|
|
setTextBackgroundColor(storyTextPost.textBackgroundColor)
|
|
setTextGravity(TextAlignment.CENTER)
|
|
|
|
hideCloseButton()
|
|
|
|
postAdjustLinkPreviewTranslationY()
|
|
}
|
|
|
|
fun bindLinkPreview(linkPreview: LinkPreview?): ListenableFuture<Boolean> {
|
|
return linkPreviewView.bind(linkPreview, View.GONE)
|
|
}
|
|
|
|
fun bindLinkPreviewState(linkPreviewState: LinkPreviewViewModel.LinkPreviewState, hiddenVisibility: Int) {
|
|
linkPreviewView.bind(linkPreviewState, hiddenVisibility)
|
|
}
|
|
|
|
fun postAdjustLinkPreviewTranslationY() {
|
|
setTextVisible(canDisplayText())
|
|
doOnNextLayout {
|
|
adjustLinkPreviewTranslationY()
|
|
}
|
|
}
|
|
|
|
fun setTextViewClickListener(onClickListener: OnClickListener) {
|
|
setOnClickListener(onClickListener)
|
|
}
|
|
|
|
fun setLinkPreviewCloseListener(onClickListener: OnClickListener) {
|
|
linkPreviewView.setOnCloseClickListener(onClickListener)
|
|
}
|
|
|
|
fun setLinkPreviewClickListener(onClickListener: OnClickListener?) {
|
|
linkPreviewView.setOnClickListener(onClickListener)
|
|
}
|
|
|
|
fun showPostContent() {
|
|
textView.alpha = 1f
|
|
linkPreviewView.alpha = 1f
|
|
}
|
|
|
|
fun hidePostContent() {
|
|
textView.alpha = 0f
|
|
linkPreviewView.alpha = 0f
|
|
}
|
|
|
|
private fun canDisplayText(): Boolean {
|
|
return !(linkPreviewView.isVisible && isPlaceholder)
|
|
}
|
|
|
|
private fun adjustLinkPreviewTranslationY() {
|
|
val backgroundHeight = backgroundView.measuredHeight
|
|
val textHeight = if (canDisplayText()) textView.measuredHeight * textView.scaleY else 0f
|
|
val previewHeight = if (linkPreviewView.visible) linkPreviewView.measuredHeight else 0
|
|
val availableHeight = backgroundHeight - textHeight
|
|
|
|
if (availableHeight >= previewHeight) {
|
|
val totalContentHeight = textHeight + previewHeight
|
|
val topAndBottomMargin = backgroundHeight - totalContentHeight
|
|
val margin = topAndBottomMargin / 2f
|
|
|
|
linkPreviewView.translationY = -margin
|
|
|
|
val originPoint = textView.measuredHeight / 2f
|
|
val desiredPoint = (textHeight / 2f) + margin
|
|
|
|
textView.translationY = desiredPoint - originPoint
|
|
} else {
|
|
linkPreviewView.translationY = 0f
|
|
|
|
val originPoint = textView.measuredHeight / 2f
|
|
val desiredPoint = backgroundHeight / 2f
|
|
|
|
textView.translationY = desiredPoint - originPoint
|
|
}
|
|
}
|
|
}
|