Updated on 2026-08-14
This commit is contained in:
parent
ac8436460c
commit
459db3d0df
17 changed files with 263 additions and 102 deletions
|
|
@ -1,36 +0,0 @@
|
|||
package com.tangem.tap.common.haptic
|
||||
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
|
||||
class DefaultHapticManager(private val vibrator: Vibrator) : HapticManager {
|
||||
|
||||
override fun vibrateShort() {
|
||||
vibrate(VIBRATION_SHORT_DURATION)
|
||||
}
|
||||
|
||||
override fun vibrateMeduim() {
|
||||
vibrate(VIBRATION_MEDIUM_LOW_DURATION)
|
||||
}
|
||||
|
||||
override fun vibrateLong() {
|
||||
vibrate(VIBRATION_MEDIUM_DURATION)
|
||||
}
|
||||
|
||||
private fun vibrate(durationMs: Long) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
} else {
|
||||
vibrator.vibrate(durationMs)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIBRATION_SHORT_DURATION = 50L
|
||||
const val VIBRATION_MEDIUM_LOW_DURATION = 75L
|
||||
const val VIBRATION_MEDIUM_DURATION = 100L
|
||||
const val VIBRATION_LONG_DURATION = 200L
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.tap.common.haptic
|
||||
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import androidx.annotation.ChecksSdkIntAtLeast
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
|
||||
internal class DefaultVibratorHapticManager(
|
||||
private val vibrator: Vibrator,
|
||||
) : VibratorHapticManager {
|
||||
|
||||
private val isHapticEnabled = deviceSupportsVibrationEffects()
|
||||
|
||||
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.Q)
|
||||
private fun deviceSupportsVibrationEffects(): Boolean = when {
|
||||
!vibrator.hasVibrator() -> false
|
||||
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ->
|
||||
vibrator.areAllEffectsSupported(
|
||||
TangemHapticEffect.OneTime.DoubleClick.code,
|
||||
TangemHapticEffect.OneTime.HeavyClick.code,
|
||||
TangemHapticEffect.OneTime.Tick.code,
|
||||
TangemHapticEffect.OneTime.Click.code,
|
||||
) == Vibrator.VIBRATION_EFFECT_SUPPORT_YES
|
||||
|
||||
Build.VERSION.SDK_INT == Build.VERSION_CODES.Q -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
|
||||
override fun performOneTime(effect: TangemHapticEffect.OneTime) {
|
||||
if (!isHapticEnabled) return
|
||||
|
||||
vibrator.vibrate(VibrationEffect.createPredefined(effect.code))
|
||||
}
|
||||
}
|
||||
|
|
@ -4,9 +4,9 @@ import android.content.Context
|
|||
import android.os.Build
|
||||
import android.os.Vibrator
|
||||
import android.os.VibratorManager
|
||||
import com.tangem.tap.common.haptic.DefaultHapticManager
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.MockHapticManager
|
||||
import com.tangem.tap.common.haptic.DefaultVibratorHapticManager
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -20,7 +20,7 @@ class HapticModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideHapticManager(@ApplicationContext context: Context): HapticManager {
|
||||
fun provideHapticManager(@ApplicationContext context: Context): VibratorHapticManager {
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator
|
||||
|
|
@ -29,9 +29,12 @@ class HapticModule {
|
|||
}
|
||||
|
||||
return if (vibrator.hasVibrator()) {
|
||||
DefaultHapticManager(vibrator = vibrator)
|
||||
DefaultVibratorHapticManager(vibrator = vibrator)
|
||||
} else {
|
||||
MockHapticManager
|
||||
// mock
|
||||
object : VibratorHapticManager {
|
||||
override fun performOneTime(effect: TangemHapticEffect.OneTime) = Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.di
|
|||
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import com.tangem.core.ui.UiDependencies
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.core.ui.message.EventMessageHandler
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import dagger.Module
|
||||
|
|
@ -17,9 +17,12 @@ internal object UiDependenciesModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUiDependencies(hapticManager: HapticManager, appThemeModeHolder: AppThemeModeHolder): UiDependencies {
|
||||
fun provideUiDependencies(
|
||||
vibratorHapticManager: VibratorHapticManager,
|
||||
appThemeModeHolder: AppThemeModeHolder,
|
||||
): UiDependencies {
|
||||
return object : UiDependencies {
|
||||
override val hapticManager = hapticManager
|
||||
override val vibratorHapticManager = vibratorHapticManager
|
||||
override val appThemeModeHolder = appThemeModeHolder
|
||||
override val globalSnackbarHostState: SnackbarHostState = SnackbarHostState()
|
||||
override val eventMessageHandler: EventMessageHandler = EventMessageHandler()
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalFontFamilyResolver
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontSynthesis
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -52,6 +50,8 @@ import com.tangem.common.ui.charts.layer.rememberTangemChartMarker
|
|||
import com.tangem.common.ui.charts.preview.MarketChartPreviewDataProvider
|
||||
import com.tangem.common.ui.charts.state.*
|
||||
import com.tangem.core.ui.components.SpacerH16
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
|
|
@ -134,7 +134,8 @@ private fun rememberMarketVisibilityListener(
|
|||
canvasWidth: Int,
|
||||
state: MarketChartState,
|
||||
): CartesianMarkerVisibilityListener {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val haptic = LocalHapticManager.current
|
||||
|
||||
return remember(state, canvasWidth) {
|
||||
val maxCanvasXFloat = canvasWidth.toFloat().takeIf { it != 0f }
|
||||
|
||||
|
|
@ -145,7 +146,7 @@ private fun rememberMarketVisibilityListener(
|
|||
state.markerFraction = maxCanvasXFloat?.let { xCanvas / it }
|
||||
state.markerVisibilityListener.onShown(marker, targets)
|
||||
|
||||
haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
|
||||
haptic.perform(TangemHapticEffect.View.ContextClick)
|
||||
}
|
||||
|
||||
override fun onHidden(marker: CartesianMarker) {
|
||||
|
|
@ -158,7 +159,8 @@ private fun rememberMarketVisibilityListener(
|
|||
|
||||
state.markerFraction = maxCanvasXFloat?.let { xCanvas / it }
|
||||
state.markerVisibilityListener.onUpdated(marker, targets)
|
||||
haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
|
||||
|
||||
haptic.perform(TangemHapticEffect.View.TextHandleMove)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ package com.tangem.core.ui
|
|||
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.core.ui.message.EventMessageHandler
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
|
||||
@Stable
|
||||
interface UiDependencies {
|
||||
|
||||
val hapticManager: HapticManager
|
||||
val vibratorHapticManager: VibratorHapticManager
|
||||
|
||||
val appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.core.ui.haptic
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.ViewCompat
|
||||
|
||||
internal class DefaultHapticManager(
|
||||
private val view: View,
|
||||
private val vibratorHapticManager: VibratorHapticManager?,
|
||||
) : HapticManager {
|
||||
|
||||
override fun perform(effect: TangemHapticEffect) {
|
||||
when (effect) {
|
||||
is TangemHapticEffect.View -> {
|
||||
effect.androidHapticFeedbackCode?.let {
|
||||
ViewCompat.performHapticFeedback(view, it)
|
||||
}
|
||||
}
|
||||
is TangemHapticEffect.OneTime -> {
|
||||
if (vibratorHapticManager != null) {
|
||||
vibratorHapticManager.performOneTime(effect)
|
||||
} else {
|
||||
when (effect) {
|
||||
TangemHapticEffect.OneTime.Tick -> perform(TangemHapticEffect.View.SegmentTick)
|
||||
TangemHapticEffect.OneTime.Click -> perform(TangemHapticEffect.View.ContextClick)
|
||||
TangemHapticEffect.OneTime.DoubleClick -> perform(TangemHapticEffect.View.ContextClick)
|
||||
TangemHapticEffect.OneTime.HeavyClick -> perform(TangemHapticEffect.View.LongPress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,13 @@ package com.tangem.core.ui.haptic
|
|||
|
||||
import androidx.compose.runtime.Stable
|
||||
|
||||
/**
|
||||
* Haptic feedback.
|
||||
* @see [TangemHapticEffect.OneTime] for one-time effects.
|
||||
* @see [TangemHapticEffect.View] for view effects.
|
||||
*/
|
||||
@Stable
|
||||
interface HapticManager {
|
||||
|
||||
fun vibrateShort()
|
||||
|
||||
fun vibrateMeduim()
|
||||
|
||||
fun vibrateLong()
|
||||
fun perform(effect: TangemHapticEffect)
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package com.tangem.core.ui.haptic
|
||||
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun MockHapticManager(mockHapticFeedback: HapticFeedback? = null): HapticManager =
|
||||
if (mockHapticFeedback == null) MockHapticManager else MockHapticManagerImpl(mockHapticFeedback)
|
||||
|
||||
val MockHapticManager: HapticManager = MockHapticManagerImpl()
|
||||
|
||||
private class MockHapticManagerImpl(
|
||||
private val mockHapticFeedback: HapticFeedback? = null,
|
||||
) : HapticManager {
|
||||
|
||||
override fun vibrateShort() {
|
||||
mockHapticFeedback?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
|
||||
/** Intentionally do nothing */
|
||||
}
|
||||
|
||||
override fun vibrateMeduim() {
|
||||
mockHapticFeedback?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
|
||||
/** Intentionally do nothing */
|
||||
}
|
||||
|
||||
override fun vibrateLong() {
|
||||
mockHapticFeedback?.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
/** Intentionally do nothing */
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package com.tangem.core.ui.haptic
|
||||
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
sealed interface TangemHapticEffect {
|
||||
|
||||
/**
|
||||
* For cases when view could not be visible on screen (ex. Activity is not in foreground)
|
||||
* or there is no view context (ex. background service, Model, ViewModel)
|
||||
*/
|
||||
enum class OneTime : TangemHapticEffect {
|
||||
Click,
|
||||
DoubleClick,
|
||||
HeavyClick,
|
||||
Tick,
|
||||
;
|
||||
|
||||
val code: Int
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
get() = when (this) {
|
||||
Click -> VibrationEffect.EFFECT_CLICK
|
||||
DoubleClick -> VibrationEffect.EFFECT_DOUBLE_CLICK
|
||||
HeavyClick -> VibrationEffect.EFFECT_HEAVY_CLICK
|
||||
Tick -> VibrationEffect.EFFECT_TICK
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preferred way to provide haptic feedback for UI components
|
||||
* @see [androidx.core.view.HapticFeedbackConstantsCompat]
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
enum class View(internal val androidHapticFeedbackCode: Int? = null) : TangemHapticEffect {
|
||||
/**
|
||||
* The user has performed a long press on an object that is resulting in an action being
|
||||
* performed
|
||||
*/
|
||||
LongPress(0),
|
||||
/**
|
||||
* The user has pressed on a virtual on-screen key
|
||||
*/
|
||||
VirtualKey(1),
|
||||
/**
|
||||
* The user has pressed either an hour or minute tick of a Clock
|
||||
*/
|
||||
ClockTick(4),
|
||||
/**
|
||||
* The user has performed a context click on an object
|
||||
*/
|
||||
ContextClick(6),
|
||||
/**
|
||||
* The user has pressed a virtual or software keyboard key
|
||||
*/
|
||||
KeyboardPress(3),
|
||||
/**
|
||||
* The user has released a virtual keyboard key
|
||||
*/
|
||||
KeyboardRelease(7),
|
||||
/**
|
||||
* The user has released a virtual key
|
||||
*/
|
||||
VirtualKeyRelease(8),
|
||||
/**
|
||||
* The user has performed a selection/insertion handle move on text field
|
||||
*/
|
||||
TextHandleMove(9),
|
||||
/**
|
||||
* The user has started a gesture (e.g. on the soft keyboard)
|
||||
*/
|
||||
GestureStart(12),
|
||||
/**
|
||||
* The user has finished a gesture (e.g. on the soft keyboard)
|
||||
*/
|
||||
GestureEnd(13),
|
||||
/**
|
||||
* A haptic effect to signal the confirmation or successful completion of a user interaction
|
||||
*/
|
||||
Confirm(16),
|
||||
/**
|
||||
* A haptic effect to signal the rejection or failure of a user interaction
|
||||
*/
|
||||
Reject(17),
|
||||
/**
|
||||
* The user has toggled a switch or button into the on position
|
||||
*/
|
||||
ToggleOn(21),
|
||||
/**
|
||||
* The user has toggled a switch or button into the off position
|
||||
*/
|
||||
ToggleOff(22),
|
||||
/**
|
||||
* The user is executing a swipe/drag-style gesture, such as pull-to-refresh, where the
|
||||
* gesture action is “eligible” at a certain threshold of movement, and can be cancelled by
|
||||
* moving back past the threshold. This constant indicates that the user's motion has just
|
||||
* passed the threshold for the action to be activated on release
|
||||
*/
|
||||
GestureThresholdActivate(23),
|
||||
/**
|
||||
* The user is executing a swipe/drag-style gesture, such as pull-to-refresh, where the
|
||||
* gesture action is “eligible” at a certain threshold of movement, and can be cancelled by
|
||||
* moving back past the threshold. This constant indicates that the user's motion has just
|
||||
* re-crossed back "under" the threshold for the action to be activated, meaning the gesture is
|
||||
* currently in a cancelled state
|
||||
*/
|
||||
GestureThresholdDeactivate(24),
|
||||
/**
|
||||
* The user has started a drag-and-drop gesture. The drag target has just been "picked up"
|
||||
*/
|
||||
DragStart(25),
|
||||
/**
|
||||
* The user is switching between a series of potential choices, for example items in a list
|
||||
* or discrete points on a slider
|
||||
*/
|
||||
SegmentTick(26),
|
||||
/**
|
||||
* The user is switching between a series of many potential choices, for example minutes on a
|
||||
* clock face, or individual percentages. This constant is expected to be very soft, so as
|
||||
* not to be uncomfortable when performed a lot in quick succession. If the device can’t make
|
||||
* a suitably soft vibration, then it may not make any vibration
|
||||
*/
|
||||
SegmentFrequentTick(27),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.core.ui.haptic
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
|
||||
/**
|
||||
* Haptic feedback
|
||||
* For cases when view could not be visible on screen (ex. Activity is not in foreground)
|
||||
* or there is no view context (ex. background service, Model, ViewModel)
|
||||
* @see [HapticManager] for view effects.
|
||||
*/
|
||||
@Stable
|
||||
interface VibratorHapticManager {
|
||||
|
||||
fun performOneTime(effect: TangemHapticEffect.OneTime)
|
||||
}
|
||||
|
|
@ -8,10 +8,12 @@ import androidx.compose.material.ProvideTextStyle
|
|||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.tangem.core.ui.components.TangemShimmer
|
||||
import com.tangem.core.ui.haptic.DefaultHapticManager
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.MockHapticManager
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.core.ui.windowsize.WindowSize
|
||||
import com.valentinilk.shimmer.Shimmer
|
||||
|
||||
|
|
@ -21,7 +23,7 @@ fun TangemTheme(
|
|||
windowSize: WindowSize,
|
||||
typography: TangemTypography = TangemTheme.typography,
|
||||
dimens: TangemDimens = TangemTheme.dimens,
|
||||
hapticManager: HapticManager = MockHapticManager,
|
||||
vibratorHapticManager: VibratorHapticManager? = null,
|
||||
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
|
|
@ -40,6 +42,12 @@ fun TangemTheme(
|
|||
)
|
||||
}
|
||||
|
||||
val view = LocalView.current
|
||||
|
||||
val hapticManager = remember(view) {
|
||||
DefaultHapticManager(view = view, vibratorHapticManager = vibratorHapticManager)
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colors = materialThemeColors(colors = themeColors, isDark = isDark),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ProvidableCompositionLocal
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import com.tangem.core.ui.haptic.MockHapticManager
|
||||
import com.tangem.core.ui.windowsize.rememberWindowSizePreview
|
||||
|
||||
@Composable
|
||||
|
|
@ -29,7 +27,6 @@ fun TangemThemePreview(
|
|||
typography = typography,
|
||||
dimens = dimens,
|
||||
windowSize = rememberWindowSizePreview(maxWidth, maxHeight),
|
||||
hapticManager = MockHapticManager(LocalHapticFeedback.current),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ internal fun ComposeScreen.createComposeView(context: Context, activity: Activit
|
|||
TangemTheme(
|
||||
isDark = shouldUseDarkTheme(appThemeMode),
|
||||
windowSize = windowSize,
|
||||
hapticManager = uiDependencies.hapticManager,
|
||||
vibratorHapticManager = uiDependencies.vibratorHapticManager,
|
||||
snackbarHostState = uiDependencies.globalSnackbarHostState,
|
||||
) {
|
||||
ScreenContent(modifier = screenModifier)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import com.tangem.core.ui.components.*
|
|||
import com.tangem.core.ui.components.currency.icon.CoinIcon
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeInPercent
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
import com.tangem.core.ui.res.LocalWindowSize
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -97,14 +98,14 @@ fun MarketsListItem(
|
|||
.collect {
|
||||
val border = -actionWidthPx * SWIPE_THRESHOLD_PERCENT
|
||||
if (it < border && actionPerformed.not()) {
|
||||
hapticManager.vibrateLong()
|
||||
hapticManager.perform(TangemHapticEffect.View.GestureThresholdActivate)
|
||||
actionPerformed = true
|
||||
releasePerformed = false
|
||||
}
|
||||
|
||||
if (it > border) {
|
||||
if (releasePerformed.not()) {
|
||||
hapticManager.vibrateShort()
|
||||
hapticManager.perform(TangemHapticEffect.View.GestureThresholdDeactivate)
|
||||
releasePerformed = true
|
||||
}
|
||||
actionPerformed = false
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.datasource.local.swaptx.SwapTransactionStatusStore
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
|
@ -120,7 +121,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val associateAssetUseCase: AssociateAssetUseCase,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val hapticManager: HapticManager,
|
||||
private val vibratorHapticManager: VibratorHapticManager,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
tokenDetailsFeatureToggles: TokenDetailsFeatureToggles,
|
||||
|
|
@ -580,7 +581,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
ifRight = { it },
|
||||
)
|
||||
if (extendedKey.isNotBlank()) {
|
||||
hapticManager.vibrateMeduim()
|
||||
vibratorHapticManager.performOneTime(TangemHapticEffect.OneTime.Click)
|
||||
clipboardManager.setText(text = extendedKey)
|
||||
internalUiState.value = stateFactory.getStateAndTriggerEvent(
|
||||
state = internalUiState.value,
|
||||
|
|
@ -802,7 +803,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
val addresses = networkAddress.availableAddresses.mapToAddressModels(cryptoCurrency).toImmutableList()
|
||||
val defaultAddress = addresses.firstOrNull()?.value ?: return null
|
||||
|
||||
hapticManager.vibrateMeduim()
|
||||
vibratorHapticManager.performOneTime(TangemHapticEffect.OneTime.Click)
|
||||
clipboardManager.setText(text = defaultAddress)
|
||||
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(cryptoCurrency.symbol))
|
||||
return resourceReference(R.string.wallet_notification_address_copied)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.WrappedList
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.haptic.HapticManager
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.extenstions.unwrap
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
|
|
@ -91,7 +92,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val hapticManager: HapticManager,
|
||||
private val vibratorHapticManager: VibratorHapticManager,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val getYieldUseCase: GetYieldUseCase,
|
||||
) : BaseWalletClickIntents(), WalletCurrencyActionsClickIntents {
|
||||
|
|
@ -192,7 +193,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
val addresses = networkAddress.availableAddresses.mapToAddressModels(cryptoCurrency).toImmutableList()
|
||||
val defaultAddress = addresses.firstOrNull()?.value ?: return null
|
||||
|
||||
hapticManager.vibrateMeduim()
|
||||
vibratorHapticManager.performOneTime(TangemHapticEffect.OneTime.Click)
|
||||
clipboardManager.setText(text = defaultAddress)
|
||||
analyticsEventHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(cryptoCurrency.symbol))
|
||||
return resourceReference(R.string.wallet_notification_address_copied)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue