Updated on 2026-08-14
This commit is contained in:
commit
cedea0f61d
6 changed files with 72 additions and 276 deletions
|
|
@ -0,0 +1,48 @@
|
|||
package com.tangem.tap.common.toggleWidget
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
open class IndeterminateProgressButtonWidget(
|
||||
private val button: MaterialButton,
|
||||
private val progress: View,
|
||||
initialState: ProgressState = ProgressState.None
|
||||
) : ViewStateWidget {
|
||||
|
||||
private var initialButtonText: CharSequence = button.text
|
||||
private var icon: Drawable? = null
|
||||
|
||||
init {
|
||||
icon = button.icon
|
||||
changeState(initialState)
|
||||
}
|
||||
|
||||
override fun changeState(state: WidgetState) {
|
||||
val progressState = state as? ProgressState ?: return
|
||||
|
||||
when (progressState) {
|
||||
is ProgressState.None -> switchToNone()
|
||||
is ProgressState.Progress -> switchToProgress()
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun switchToNone() {
|
||||
button.isClickable = true
|
||||
button.icon = icon
|
||||
button.text = initialButtonText
|
||||
progress.hide()
|
||||
}
|
||||
|
||||
protected open fun switchToProgress() {
|
||||
button.isClickable = false
|
||||
button.icon = null
|
||||
button.text = ""
|
||||
progress.show()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
package com.tangem.merchant.common.toggleWidget
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface ToggleState
|
||||
|
||||
interface StateModifier {
|
||||
fun stateChanged(container: ViewGroup, view: View, state: ToggleState)
|
||||
}
|
||||
|
||||
interface ToggleView {
|
||||
val mainViewModifiers: MutableList<StateModifier>
|
||||
val toggleViewModifiers: MutableList<StateModifier>
|
||||
|
||||
fun setState(state: ToggleState, andApply: Boolean = true)
|
||||
fun applyState()
|
||||
fun getView(): View
|
||||
fun getMainView(): View
|
||||
fun getToggleView(): View
|
||||
}
|
||||
|
||||
class ToggleWidget : ToggleView {
|
||||
private val container: ViewGroup
|
||||
private val mainView: View
|
||||
private val toggleView: View
|
||||
|
||||
private var state: ToggleState
|
||||
|
||||
constructor(
|
||||
container: ViewGroup,
|
||||
mainView: View,
|
||||
toggleView: View,
|
||||
initialState: ToggleState,
|
||||
mainViewModifier: List<StateModifier> = mutableListOf(),
|
||||
loadingViewModifier: List<StateModifier> = mutableListOf()
|
||||
) {
|
||||
this.container = container
|
||||
this.mainView = mainView
|
||||
this.toggleView = toggleView
|
||||
this.state = initialState
|
||||
this.mainViewModifiers.addAll(mainViewModifier)
|
||||
this.toggleViewModifiers.addAll(loadingViewModifier)
|
||||
}
|
||||
|
||||
constructor(
|
||||
container: ViewGroup,
|
||||
mainViewId: Int,
|
||||
toggleViewId: Int,
|
||||
initialState: ToggleState,
|
||||
mainViewModifier: List<StateModifier> = mutableListOf(),
|
||||
loadingViewModifier: List<StateModifier> = mutableListOf()
|
||||
) {
|
||||
this.container = container
|
||||
this.mainView = container.findViewById(mainViewId)
|
||||
this.toggleView = container.findViewById(toggleViewId)
|
||||
this.state = initialState
|
||||
this.mainViewModifiers.addAll(mainViewModifier)
|
||||
this.toggleViewModifiers.addAll(loadingViewModifier)
|
||||
}
|
||||
|
||||
override val mainViewModifiers: MutableList<StateModifier> = mutableListOf()
|
||||
|
||||
override val toggleViewModifiers: MutableList<StateModifier> = mutableListOf()
|
||||
|
||||
override fun setState(state: ToggleState, andApply: Boolean) {
|
||||
this.state = state
|
||||
if (andApply) applyState()
|
||||
}
|
||||
|
||||
override fun applyState() {
|
||||
mainViewModifiers.forEach { it.stateChanged(container, mainView, state) }
|
||||
toggleViewModifiers.forEach { it.stateChanged(container, toggleView, state) }
|
||||
}
|
||||
|
||||
override fun getView(): View = container
|
||||
|
||||
override fun getMainView(): View = mainView
|
||||
|
||||
override fun getToggleView(): View = toggleView
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.tap.common.toggleWidget
|
||||
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface WidgetState
|
||||
|
||||
interface ViewStateWidget {
|
||||
fun changeState(state: WidgetState)
|
||||
}
|
||||
|
||||
sealed class ProgressState : WidgetState {
|
||||
object None : ProgressState()
|
||||
data class Progress(val progress: Int = 0) : ProgressState()
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
package com.tangem.tap.common.toggleWidget
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.tangem.merchant.common.toggleWidget.StateModifier
|
||||
import com.tangem.merchant.common.toggleWidget.ToggleState
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
||||
sealed class ProgressState : ToggleState {
|
||||
class Progress : ProgressState()
|
||||
class None : ProgressState()
|
||||
}
|
||||
|
||||
class ReplaceTextStateModifier(
|
||||
private val initialText: String,
|
||||
private val replaceText: String = ""
|
||||
) : StateModifier {
|
||||
|
||||
override fun stateChanged(container: ViewGroup, view: View, state: ToggleState) {
|
||||
val tv = view as? TextView ?: return
|
||||
|
||||
when (state) {
|
||||
is ProgressState.Progress -> {
|
||||
tv.text = replaceText
|
||||
}
|
||||
is ProgressState.None -> {
|
||||
tv.text = initialText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TextViewDrawableStateModifier(
|
||||
private val initialDrawable: Drawable?,
|
||||
private val replaceDrawable: Drawable?,
|
||||
private val position: Int
|
||||
) : StateModifier {
|
||||
companion object {
|
||||
val LEFT = 1
|
||||
val RIGHT = 2
|
||||
}
|
||||
|
||||
override fun stateChanged(container: ViewGroup, view: View, state: ToggleState) {
|
||||
val drawable = when (state) {
|
||||
is ProgressState.Progress -> replaceDrawable
|
||||
is ProgressState.None -> initialDrawable
|
||||
else -> null
|
||||
}
|
||||
val drawableChanger = getChanger(view)
|
||||
drawableChanger?.change(drawable, position)
|
||||
}
|
||||
|
||||
private fun getChanger(view: View): DrawableChanger? = when (view) {
|
||||
is MaterialButton -> MaterialButtonChanger(view)
|
||||
is Button -> TextViewChanger(view)
|
||||
is TextView -> TextViewChanger(view)
|
||||
else -> null
|
||||
}
|
||||
|
||||
internal interface DrawableChanger {
|
||||
fun change(drawable: Drawable?, position: Int)
|
||||
}
|
||||
|
||||
internal class TextViewChanger(private val view: TextView) : DrawableChanger {
|
||||
override fun change(drawable: Drawable?, position: Int) {
|
||||
when (position) {
|
||||
LEFT -> setLeft(drawable)
|
||||
RIGHT -> setRight(drawable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setLeft(drawable: Drawable?) {
|
||||
if (drawable == null) {
|
||||
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(view, 0, 0, 0, 0)
|
||||
} else {
|
||||
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(view, drawable, null, null, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRight(drawable: Drawable?) {
|
||||
if (drawable == null) {
|
||||
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(view, 0, 0, 0, 0)
|
||||
} else {
|
||||
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(view, null, null, drawable, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class MaterialButtonChanger(private val view: MaterialButton) : DrawableChanger {
|
||||
override fun change(drawable: Drawable?, position: Int) {
|
||||
when (position) {
|
||||
LEFT -> setLeft(drawable)
|
||||
RIGHT -> setRight(drawable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setLeft(drawable: Drawable?) {
|
||||
view.iconGravity = MaterialButton.ICON_GRAVITY_START
|
||||
view.icon = drawable
|
||||
}
|
||||
|
||||
private fun setRight(drawable: Drawable?) {
|
||||
view.iconGravity = MaterialButton.ICON_GRAVITY_END
|
||||
view.icon = drawable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ShowHideStateModifier(
|
||||
private val isShowOnLoading: Boolean = true,
|
||||
private val typeOfHiding: Int = View.INVISIBLE
|
||||
) : StateModifier {
|
||||
|
||||
override fun stateChanged(container: ViewGroup, view: View, state: ToggleState) {
|
||||
container.beginDelayedTransition()
|
||||
view.visibility = when (state) {
|
||||
is ProgressState.Progress -> if (isShowOnLoading) View.VISIBLE else typeOfHiding
|
||||
is ProgressState.None -> if (isShowOnLoading) typeOfHiding else View.VISIBLE
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ClickableStateModifier(
|
||||
private val isClickableOnLoading: Boolean = false
|
||||
) : StateModifier {
|
||||
|
||||
override fun stateChanged(container: ViewGroup, view: View, state: ToggleState) {
|
||||
view.isClickable = when (state) {
|
||||
is ProgressState.Progress -> isClickableOnLoading
|
||||
is ProgressState.None -> !isClickableOnLoading
|
||||
else -> return
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,12 +13,10 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.tangem.Message
|
||||
import com.tangem.merchant.common.toggleWidget.ToggleWidget
|
||||
import com.tangem.tangem_sdk_new.extensions.dpToPx
|
||||
import com.tangem.tangem_sdk_new.extensions.hideSoftKeyboard
|
||||
import com.tangem.tap.common.KeyboardObserver
|
||||
import com.tangem.tap.common.entities.TapCurrency
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
import com.tangem.tap.common.extensions.setOnImeActionListener
|
||||
import com.tangem.tap.common.qrCodeScan.ScanQrCodeActivity
|
||||
|
|
@ -55,17 +53,11 @@ import java.text.DecimalFormatSymbols
|
|||
*/
|
||||
class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
||||
|
||||
lateinit var sendBtn: ToggleWidget
|
||||
lateinit var sendBtn: ViewStateWidget
|
||||
|
||||
private lateinit var etAmountToSend: TextInputEditText
|
||||
private lateinit var warningsAdapter: WarningMessagesAdapter
|
||||
|
||||
private fun initSendButtonStates() {
|
||||
sendBtn = ToggleWidget(flSendButtonContainer, btnSend, progress, ProgressState.None())
|
||||
sendBtn.setupSendButtonStateModifiers(requireContext())
|
||||
sendBtn.setState(ProgressState.None())
|
||||
}
|
||||
|
||||
private val sendSubscriber = SendStateSubscriber(this)
|
||||
private lateinit var keyboardObserver: KeyboardObserver
|
||||
|
||||
|
|
@ -80,12 +72,15 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
setupAmountLayout()
|
||||
setupFeeLayout()
|
||||
setupWarningMessages()
|
||||
}
|
||||
|
||||
private fun initSendButtonStates() {
|
||||
btnSend.setOnClickListener {
|
||||
store.dispatch(SendActionUi.SendAmountToRecipient(
|
||||
Message(getString(R.string.initial_message_sign_header))
|
||||
))
|
||||
}
|
||||
sendBtn = IndeterminateProgressButtonWidget(btnSend, progress)
|
||||
}
|
||||
|
||||
private fun setupAddressOrPayIdLayout() {
|
||||
|
|
@ -300,37 +295,4 @@ class FeeUiHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//class MemoUiHelper {
|
||||
// companion object {
|
||||
// fun toId(memo: MemoType): Int {
|
||||
// return when (memo) {
|
||||
// MemoType.TEXT -> R.id.chipMemoText
|
||||
// MemoType.ID -> R.id.chipMemoId
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun toType(id: Int): MemoType {
|
||||
// return when (id) {
|
||||
// R.id.chipMemoText -> MemoType.TEXT
|
||||
// R.id.chipMemoId -> MemoType.ID
|
||||
// else -> MemoType.TEXT
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
private fun ToggleWidget.setupSendButtonStateModifiers(context: Context) {
|
||||
mainViewModifiers.clear()
|
||||
mainViewModifiers.add(ReplaceTextStateModifier(context.getString(R.string.send_title), ""))
|
||||
mainViewModifiers.add(
|
||||
TextViewDrawableStateModifier(
|
||||
context.getDrawableCompat(R.drawable.ic_arrow_right), null, TextViewDrawableStateModifier.RIGHT
|
||||
))
|
||||
mainViewModifiers.add(ClickableStateModifier())
|
||||
toggleViewModifiers.clear()
|
||||
toggleViewModifiers.add(ShowHideStateModifier())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -119,15 +119,15 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
when (state.sendButtonState) {
|
||||
SendButtonState.ENABLED -> {
|
||||
fg.btnSend.isEnabled = true
|
||||
sendFragment.sendBtn.setState(ProgressState.None(), true)
|
||||
sendFragment.sendBtn.changeState(ProgressState.None)
|
||||
}
|
||||
SendButtonState.DISABLED -> {
|
||||
fg.btnSend.isEnabled = false
|
||||
sendFragment.sendBtn.setState(ProgressState.None(), true)
|
||||
sendFragment.sendBtn.changeState(ProgressState.None)
|
||||
}
|
||||
SendButtonState.PROGRESS -> {
|
||||
fg.btnSend.isEnabled = true
|
||||
sendFragment.sendBtn.setState(ProgressState.Progress(), true)
|
||||
sendFragment.sendBtn.changeState(ProgressState.Progress())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue