Updated on 2026-08-14
This commit is contained in:
parent
e4d637927a
commit
2a021f7d03
14 changed files with 155 additions and 76 deletions
|
|
@ -34,9 +34,7 @@ import com.tangem.core.decompose.di.RootAppComponentContext
|
||||||
import com.tangem.core.deeplink.DEEPLINK_KEY
|
import com.tangem.core.deeplink.DEEPLINK_KEY
|
||||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||||
import com.tangem.core.deeplink.WEBLINK_KEY
|
import com.tangem.core.deeplink.WEBLINK_KEY
|
||||||
import com.tangem.core.navigation.email.EmailSender
|
|
||||||
import com.tangem.core.navigation.url.UrlOpener
|
import com.tangem.core.navigation.url.UrlOpener
|
||||||
import com.tangem.core.ui.UiDependencies
|
|
||||||
import com.tangem.data.balancehiding.DefaultDeviceFlipDetector
|
import com.tangem.data.balancehiding.DefaultDeviceFlipDetector
|
||||||
import com.tangem.data.card.sdk.CardSdkOwner
|
import com.tangem.data.card.sdk.CardSdkOwner
|
||||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||||
|
|
@ -53,6 +51,7 @@ import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
|
||||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||||
|
import com.tangem.features.tester.api.TesterMenuLauncher
|
||||||
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
import com.tangem.features.walletconnect.components.WalletConnectFeatureToggles
|
||||||
import com.tangem.google.GoogleServicesHelper
|
import com.tangem.google.GoogleServicesHelper
|
||||||
import com.tangem.operations.backup.BackupService
|
import com.tangem.operations.backup.BackupService
|
||||||
|
|
@ -69,7 +68,6 @@ import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandle
|
||||||
import com.tangem.tap.features.intentHandler.handlers.OnPushClickedIntentHandler
|
import com.tangem.tap.features.intentHandler.handlers.OnPushClickedIntentHandler
|
||||||
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
|
import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
|
||||||
import com.tangem.tap.features.main.MainViewModel
|
import com.tangem.tap.features.main.MainViewModel
|
||||||
import com.tangem.tap.proxy.AppStateHolder
|
|
||||||
import com.tangem.tap.proxy.redux.DaggerGraphAction
|
import com.tangem.tap.proxy.redux.DaggerGraphAction
|
||||||
import com.tangem.tap.routing.component.RoutingComponent
|
import com.tangem.tap.routing.component.RoutingComponent
|
||||||
import com.tangem.tap.routing.configurator.AppRouterConfig
|
import com.tangem.tap.routing.configurator.AppRouterConfig
|
||||||
|
|
@ -103,9 +101,6 @@ val mainScope = CoroutineScope(mainCoroutineContext)
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var appStateHolder: AppStateHolder
|
|
||||||
|
|
||||||
/** Router for opening tester menu */
|
/** Router for opening tester menu */
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var cardSdkOwner: CardSdkOwner
|
lateinit var cardSdkOwner: CardSdkOwner
|
||||||
|
|
@ -143,9 +138,6 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userWalletsListManager: UserWalletsListManager
|
lateinit var userWalletsListManager: UserWalletsListManager
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var emailSender: EmailSender
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@RootAppComponentContext
|
@RootAppComponentContext
|
||||||
internal lateinit var rootComponentContext: AppComponentContext
|
internal lateinit var rootComponentContext: AppComponentContext
|
||||||
|
|
@ -174,9 +166,6 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var dispatchers: CoroutineDispatcherProvider
|
lateinit var dispatchers: CoroutineDispatcherProvider
|
||||||
|
|
||||||
@Inject
|
|
||||||
internal lateinit var uiDependencies: UiDependencies
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
internal lateinit var defaultDeviceFlipDetector: DefaultDeviceFlipDetector
|
internal lateinit var defaultDeviceFlipDetector: DefaultDeviceFlipDetector
|
||||||
|
|
||||||
|
|
@ -192,6 +181,9 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||||
@Inject
|
@Inject
|
||||||
internal lateinit var urlOpener: UrlOpener
|
internal lateinit var urlOpener: UrlOpener
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
internal lateinit var testerMenuLauncher: TesterMenuLauncher
|
||||||
|
|
||||||
internal val viewModel: MainViewModel by viewModels()
|
internal val viewModel: MainViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
|
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
|
||||||
|
|
@ -251,6 +243,10 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||||
|
|
||||||
lifecycle.addObserver(WindowObscurationObserver)
|
lifecycle.addObserver(WindowObscurationObserver)
|
||||||
lifecycle.addObserver(defaultDeviceFlipDetector)
|
lifecycle.addObserver(defaultDeviceFlipDetector)
|
||||||
|
|
||||||
|
if (BuildConfig.TESTER_MENU_ENABLED) {
|
||||||
|
lifecycle.addObserver(testerMenuLauncher.launchOnShakeObserver)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setRootContent() {
|
private fun setRootContent() {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import com.tangem.features.send.v2.api.NFTSendComponent
|
||||||
import com.tangem.features.send.v2.api.SendComponent
|
import com.tangem.features.send.v2.api.SendComponent
|
||||||
import com.tangem.features.staking.api.StakingComponent
|
import com.tangem.features.staking.api.StakingComponent
|
||||||
import com.tangem.features.swap.SwapComponent
|
import com.tangem.features.swap.SwapComponent
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
|
||||||
import com.tangem.features.tokendetails.TokenDetailsComponent
|
import com.tangem.features.tokendetails.TokenDetailsComponent
|
||||||
import com.tangem.features.wallet.WalletEntryComponent
|
import com.tangem.features.wallet.WalletEntryComponent
|
||||||
import com.tangem.features.walletconnect.components.WalletConnectEntryComponent
|
import com.tangem.features.walletconnect.components.WalletConnectEntryComponent
|
||||||
|
|
@ -86,7 +85,6 @@ internal class ChildFactory @Inject constructor(
|
||||||
private val createWalletSelectionComponentFactory: CreateWalletSelectionComponent.Factory,
|
private val createWalletSelectionComponentFactory: CreateWalletSelectionComponent.Factory,
|
||||||
private val createMobileWalletComponentFactory: CreateMobileWalletComponent.Factory,
|
private val createMobileWalletComponentFactory: CreateMobileWalletComponent.Factory,
|
||||||
private val addExistingWalletComponentFactory: AddExistingWalletComponent.Factory,
|
private val addExistingWalletComponentFactory: AddExistingWalletComponent.Factory,
|
||||||
private val testerRouter: TesterRouter,
|
|
||||||
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
@ -132,9 +130,6 @@ internal class ChildFactory @Inject constructor(
|
||||||
componentFactory = welcomeComponentFactory,
|
componentFactory = welcomeComponentFactory,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is AppRoute.TesterMenu -> {
|
|
||||||
Child.LegacyIntent(testerRouter.getEntryIntent())
|
|
||||||
}
|
|
||||||
is AppRoute.WalletSettings -> {
|
is AppRoute.WalletSettings -> {
|
||||||
createComponentChild(
|
createComponentChild(
|
||||||
context = context,
|
context = context,
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,6 @@ sealed class AppRoute(val path: String) : Route {
|
||||||
) : AppRoute(path = "/welcome"), RouteBundleParams {
|
) : AppRoute(path = "/welcome"), RouteBundleParams {
|
||||||
|
|
||||||
override fun getBundle(): Bundle = bundle(serializer())
|
override fun getBundle(): Bundle = bundle(serializer())
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val INITIAL_INTENT_KEY = "intent"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
@ -177,9 +173,6 @@ sealed class AppRoute(val path: String) : Route {
|
||||||
"/$isInitialReverseOrder",
|
"/$isInitialReverseOrder",
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data object TesterMenu : AppRoute(path = "/tester_menu")
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object AppCurrencySelector : AppRoute(path = "/app_currency_selector")
|
data object AppCurrencySelector : AppRoute(path = "/app_currency_selector")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,8 @@ import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.core.ui.components.block.model.BlockUM
|
import com.tangem.core.ui.components.block.model.BlockUM
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
import com.tangem.features.details.entity.DetailsItemUM
|
import com.tangem.features.details.entity.DetailsItemUM
|
||||||
import com.tangem.features.details.impl.BuildConfig
|
|
||||||
import com.tangem.features.details.impl.R
|
import com.tangem.features.details.impl.R
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -76,17 +74,6 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) {
|
||||||
onClick = { router.push(AppRoute.AppSettings) },
|
onClick = { router.push(AppRoute.AppSettings) },
|
||||||
),
|
),
|
||||||
).let(::add)
|
).let(::add)
|
||||||
|
|
||||||
if (BuildConfig.TESTER_MENU_ENABLED) {
|
|
||||||
DetailsItemUM.Basic.Item(
|
|
||||||
id = "tester_menu",
|
|
||||||
block = BlockUM(
|
|
||||||
text = stringReference(value = "Tester menu"),
|
|
||||||
iconRes = R.drawable.ic_alert_24,
|
|
||||||
onClick = { router.push(AppRoute.TesterMenu) },
|
|
||||||
),
|
|
||||||
).let(::add)
|
|
||||||
}
|
|
||||||
}.toImmutableList(),
|
}.toImmutableList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,8 @@ plugins {
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.tangem.features.tester.api"
|
namespace = "com.tangem.features.tester.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(deps.lifecycle.common.java8)
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.tangem.features.tester.api
|
||||||
|
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for launching the tester menu
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
interface TesterMenuLauncher {
|
||||||
|
|
||||||
|
/** Observer for detecting shake events and launching the tester menu */
|
||||||
|
val launchOnShakeObserver: DefaultLifecycleObserver
|
||||||
|
}
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package com.tangem.features.tester.api
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Outer tester feature router
|
|
||||||
*
|
|
||||||
[REDACTED_AUTHOR]
|
|
||||||
*/
|
|
||||||
interface TesterRouter {
|
|
||||||
|
|
||||||
/** Open tester menu */
|
|
||||||
fun getEntryIntent(): Intent
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.tangem.feature.tester.di
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.tangem.feature.tester.presentation.navigation.DefaultTesterMenuLauncher
|
||||||
|
import com.tangem.features.tester.api.TesterMenuLauncher
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
internal object TesterMenuLauncherModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideTesterMenuLauncher(@ApplicationContext context: Context): TesterMenuLauncher {
|
||||||
|
return DefaultTesterMenuLauncher(context = context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.tangem.feature.tester.di
|
package com.tangem.feature.tester.di
|
||||||
|
|
||||||
import com.tangem.feature.tester.presentation.navigation.DefaultTesterRouter
|
import com.tangem.feature.tester.presentation.navigation.DefaultTesterRouter
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -14,5 +14,5 @@ internal interface TesterRouterModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@ActivityScoped
|
@ActivityScoped
|
||||||
fun bindTesterRouter(defaultTesterRouter: DefaultTesterRouter): TesterRouter
|
fun bindTesterRouter(defaultTesterRouter: DefaultTesterRouter): InnerTesterRouter
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +32,6 @@ import com.tangem.feature.tester.presentation.providers.ui.BlockchainProvidersSc
|
||||||
import com.tangem.feature.tester.presentation.providers.viewmodel.BlockchainProvidersViewModel
|
import com.tangem.feature.tester.presentation.providers.viewmodel.BlockchainProvidersViewModel
|
||||||
import com.tangem.feature.tester.presentation.testpush.ui.TestPushScreen
|
import com.tangem.feature.tester.presentation.testpush.ui.TestPushScreen
|
||||||
import com.tangem.feature.tester.presentation.testpush.viewmodel.TestPushViewModel
|
import com.tangem.feature.tester.presentation.testpush.viewmodel.TestPushViewModel
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.collections.immutable.persistentSetOf
|
import kotlinx.collections.immutable.persistentSetOf
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -44,9 +43,8 @@ internal class TesterActivity : ComposeActivity() {
|
||||||
@Inject
|
@Inject
|
||||||
override lateinit var uiDependencies: UiDependencies
|
override lateinit var uiDependencies: UiDependencies
|
||||||
|
|
||||||
/** Router for inner feature navigation */
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var testerRouter: TesterRouter
|
lateinit var innerTesterRouter: InnerTesterRouter
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appFinisher: AppFinisher
|
lateinit var appFinisher: AppFinisher
|
||||||
|
|
@ -54,11 +52,6 @@ internal class TesterActivity : ComposeActivity() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appRouter: AppRouter
|
lateinit var appRouter: AppRouter
|
||||||
|
|
||||||
private val innerTesterRouter: InnerTesterRouter
|
|
||||||
get() = requireNotNull(testerRouter as? InnerTesterRouter) {
|
|
||||||
"TesterRouter must be InnerTesterRouter for tester feature"
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ScreenContent(modifier: Modifier) {
|
override fun ScreenContent(modifier: Modifier) {
|
||||||
val systemBarsColor = TangemTheme.colors.background.secondary
|
val systemBarsColor = TangemTheme.colors.background.secondary
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.tangem.feature.tester.presentation.navigation
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.hardware.Sensor
|
||||||
|
import android.hardware.SensorManager
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import com.tangem.feature.tester.presentation.TesterActivity
|
||||||
|
import com.tangem.features.tester.api.TesterMenuLauncher
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of [TesterMenuLauncher] that listens for shake events using the device's accelerometer.
|
||||||
|
* When a shake is detected, it opens the tester menu.
|
||||||
|
*
|
||||||
|
* @param context the application context used to access system services
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
internal class DefaultTesterMenuLauncher(private val context: Context) : TesterMenuLauncher {
|
||||||
|
|
||||||
|
override val launchOnShakeObserver: DefaultLifecycleObserver by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
|
createObserver(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createObserver(context: Context): DefaultLifecycleObserver {
|
||||||
|
return object : DefaultLifecycleObserver {
|
||||||
|
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||||
|
private val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
|
||||||
|
private val shakeEventListener = ShakeEventListener(action = ::openTesterMenu)
|
||||||
|
|
||||||
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
|
accelerometer?.let {
|
||||||
|
sensorManager.registerListener(
|
||||||
|
/* listener = */ shakeEventListener,
|
||||||
|
/* sensor = */ it,
|
||||||
|
/* samplingPeriodUs = */ SensorManager.SENSOR_DELAY_NORMAL,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause(owner: LifecycleOwner) {
|
||||||
|
sensorManager.unregisterListener(shakeEventListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openTesterMenu() {
|
||||||
|
val intent = Intent(context, TesterActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,19 @@
|
||||||
package com.tangem.feature.tester.presentation.navigation
|
package com.tangem.feature.tester.presentation.navigation
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.tangem.feature.tester.presentation.TesterActivity
|
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
|
||||||
import dagger.hilt.android.scopes.ActivityScoped
|
import dagger.hilt.android.scopes.ActivityScoped
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of router for tester feature
|
* Implementation of router for tester feature
|
||||||
*
|
*
|
||||||
* @property context activity context
|
|
||||||
*
|
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
@ActivityScoped
|
@ActivityScoped
|
||||||
internal class DefaultTesterRouter @Inject constructor(
|
internal class DefaultTesterRouter @Inject constructor() : InnerTesterRouter {
|
||||||
@ActivityContext private val context: Context,
|
|
||||||
) : InnerTesterRouter {
|
|
||||||
|
|
||||||
private var navController: NavController? = null
|
private var navController: NavController? = null
|
||||||
|
|
||||||
override fun getEntryIntent(): Intent {
|
|
||||||
return Intent(context, TesterActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setNavController(navController: NavController) {
|
override fun setNavController(navController: NavController) {
|
||||||
this.navController = navController
|
this.navController = navController
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
package com.tangem.feature.tester.presentation.navigation
|
package com.tangem.feature.tester.presentation.navigation
|
||||||
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.tangem.features.tester.api.TesterRouter
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner feature router
|
* Inner feature router
|
||||||
*
|
*
|
||||||
[REDACTED_AUTHOR]
|
[REDACTED_AUTHOR]
|
||||||
*/
|
*/
|
||||||
internal interface InnerTesterRouter : TesterRouter {
|
internal interface InnerTesterRouter {
|
||||||
|
|
||||||
/** Set up a navigation controller that bound to tester navigation graph */
|
/** Set up a navigation controller that bound to tester navigation graph */
|
||||||
fun setNavController(navController: NavController)
|
fun setNavController(navController: NavController)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.tangem.feature.tester.presentation.navigation
|
||||||
|
|
||||||
|
import android.hardware.Sensor
|
||||||
|
import android.hardware.SensorEvent
|
||||||
|
import android.hardware.SensorEventListener
|
||||||
|
import android.hardware.SensorManager
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for device shake events.
|
||||||
|
*
|
||||||
|
* This class implements [SensorEventListener] and is used to detect device shaking based on accelerometer data.
|
||||||
|
* When a shake is detected, the provided action is invoked.
|
||||||
|
*
|
||||||
|
* @property action lambda function to be called when a shake is detected
|
||||||
|
*
|
||||||
|
[REDACTED_AUTHOR]
|
||||||
|
*/
|
||||||
|
internal class ShakeEventListener(private val action: () -> Unit) : SensorEventListener {
|
||||||
|
|
||||||
|
private var lastShakeTime = 0L
|
||||||
|
|
||||||
|
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) = Unit
|
||||||
|
|
||||||
|
override fun onSensorChanged(event: SensorEvent?) {
|
||||||
|
if (event?.sensor?.type != Sensor.TYPE_ACCELEROMETER) return
|
||||||
|
|
||||||
|
val acceleration = calculateAcceleration(event = event)
|
||||||
|
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
val currentShakeInterval = currentTime - lastShakeTime
|
||||||
|
|
||||||
|
if (acceleration > SHAKE_THRESHOLD && currentShakeInterval > SHAKE_INTERVAL_MS) {
|
||||||
|
lastShakeTime = currentTime
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculateAcceleration(event: SensorEvent): Float {
|
||||||
|
val (x, y, z) = event.toXYZ()
|
||||||
|
|
||||||
|
return sqrt(x * x + y * y + z * z) - SensorManager.GRAVITY_EARTH
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SensorEvent.toXYZ() = Triple(values[0], values[1], values[2])
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private const val SHAKE_THRESHOLD: Float = 12f
|
||||||
|
private const val SHAKE_INTERVAL_MS: Long = 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue