diff --git a/app/src/main/java/com/tangem/tap/common/haptic/DefaultHapticManager.kt b/app/src/main/java/com/tangem/tap/common/haptic/DefaultHapticManager.kt deleted file mode 100644 index 688dea7f67..0000000000 --- a/app/src/main/java/com/tangem/tap/common/haptic/DefaultHapticManager.kt +++ /dev/null @@ -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 - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/haptic/DefaultVibratorHapticManager.kt b/app/src/main/java/com/tangem/tap/common/haptic/DefaultVibratorHapticManager.kt new file mode 100644 index 0000000000..2bcae01131 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/haptic/DefaultVibratorHapticManager.kt @@ -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)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/HapticModule.kt b/app/src/main/java/com/tangem/tap/di/HapticModule.kt index bf8439f09e..dc04a3ce72 100644 --- a/app/src/main/java/com/tangem/tap/di/HapticModule.kt +++ b/app/src/main/java/com/tangem/tap/di/HapticModule.kt @@ -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 + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt b/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt index 22a522e553..44631d4c05 100644 --- a/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt +++ b/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt @@ -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() diff --git a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt index 3dca540806..4e43d74718 100644 --- a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt +++ b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt @@ -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) } } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/UiDependencies.kt b/core/ui/src/main/java/com/tangem/core/ui/UiDependencies.kt index 49a90c5af6..0db95df8d1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/UiDependencies.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/UiDependencies.kt @@ -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 diff --git a/core/ui/src/main/java/com/tangem/core/ui/haptic/DefaultHapticManager.kt b/core/ui/src/main/java/com/tangem/core/ui/haptic/DefaultHapticManager.kt new file mode 100644 index 0000000000..5a34d92702 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/haptic/DefaultHapticManager.kt @@ -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) + } + } + } + } + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/haptic/HapticManager.kt b/core/ui/src/main/java/com/tangem/core/ui/haptic/HapticManager.kt index b93c08bd26..9b0d3cd124 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/haptic/HapticManager.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/haptic/HapticManager.kt @@ -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) } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/haptic/MockHapticManager.kt b/core/ui/src/main/java/com/tangem/core/ui/haptic/MockHapticManager.kt deleted file mode 100644 index ad74ee1bd1..0000000000 --- a/core/ui/src/main/java/com/tangem/core/ui/haptic/MockHapticManager.kt +++ /dev/null @@ -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 */ - } -} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/haptic/TangemHapticEffect.kt b/core/ui/src/main/java/com/tangem/core/ui/haptic/TangemHapticEffect.kt new file mode 100644 index 0000000000..4be47d804d --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/haptic/TangemHapticEffect.kt @@ -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), + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/haptic/VibratorHapticManager.kt b/core/ui/src/main/java/com/tangem/core/ui/haptic/VibratorHapticManager.kt new file mode 100644 index 0000000000..f152a10aca --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/haptic/VibratorHapticManager.kt @@ -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) +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt index 65ffdd461b..999276faf5 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemTheme.kt @@ -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), ) { diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemThemePreview.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemThemePreview.kt index c3ed096dce..0347ca4893 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemThemePreview.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemThemePreview.kt @@ -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, ) } diff --git a/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeScreen.kt b/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeScreen.kt index d6b1869ec5..5557002b53 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeScreen.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeScreen.kt @@ -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) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt index e68c508ef5..14873a4e8d 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListItem.kt @@ -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 diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index 718cb21cf6..67e0caa285 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -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) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt index bdf5dae4ba..9ec62dbe52 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt @@ -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)