feat: ui haptics
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.nfc" android:required="false" />
|
||||
|
||||
@@ -58,10 +58,14 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bitcointxoko.gudariwallet.LocalAppStrings
|
||||
import com.bitcointxoko.gudariwallet.ui.ReceiveState
|
||||
import com.bitcointxoko.gudariwallet.ui.SendState
|
||||
import com.bitcointxoko.gudariwallet.ui.WalletViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.components.UnitWheelPicker
|
||||
import com.bitcointxoko.gudariwallet.ui.nfc.NfcViewModel
|
||||
import com.bitcointxoko.gudariwallet.util.buildUpTaps
|
||||
import com.bitcointxoko.gudariwallet.util.doubleTap
|
||||
import com.bitcointxoko.gudariwallet.util.fiatLabel
|
||||
import com.bitcointxoko.gudariwallet.util.heavyClick
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
@@ -107,6 +111,14 @@ fun ReceiveScreen(
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(receiveState) {
|
||||
when (receiveState) {
|
||||
is ReceiveState.PaymentReceived -> context.buildUpTaps()
|
||||
// is SendState.Error -> context.errorBuzz()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
if (receiveState !is ReceiveState.InvoiceReady) {
|
||||
Column(
|
||||
|
||||
@@ -31,8 +31,10 @@ import com.bitcointxoko.gudariwallet.ui.WalletViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.nfc.NfcViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.receive.AmountDisplay
|
||||
import com.bitcointxoko.gudariwallet.util.SendInputDetector
|
||||
import com.bitcointxoko.gudariwallet.util.doubleTap
|
||||
import com.bitcointxoko.gudariwallet.util.feePpm
|
||||
import com.bitcointxoko.gudariwallet.util.fiatLabel
|
||||
import com.bitcointxoko.gudariwallet.util.heavyClick
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -82,6 +84,16 @@ fun SendScreen(
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(sendState) {
|
||||
when (sendState) {
|
||||
is SendState.Bolt11Decoded,
|
||||
is SendState.LnurlInvoiceReady -> context.doubleTap()
|
||||
is SendState.PaymentSent -> context.heavyClick()
|
||||
// is SendState.Error -> context.errorBuzz()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.bitcointxoko.gudariwallet.util
|
||||
|
||||
import android.content.Context
|
||||
import android.os.*
|
||||
|
||||
fun Context.heavyClick() {
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
(getSystemService(VibratorManager::class.java)).defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK))
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(50L, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.doubleTap() {
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
(getSystemService(VibratorManager::class.java)).defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK))
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(50L, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.buildUpTaps() {
|
||||
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
(getSystemService(VibratorManager::class.java)).defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// Timings: off, on, off, on, off, on, off, FINAL ON
|
||||
val timings = longArrayOf(0, 30, 80, 30, 50, 30, 20, 60)
|
||||
val amplitudes = intArrayOf(0, 60, 0, 90, 0, 140, 0, 255)
|
||||
// ^gap ^tap ^gap ^tap ^gap ^tap ^gap ^THUD
|
||||
|
||||
vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, -1))
|
||||
} else {
|
||||
// Legacy fallback — simple triple-tap
|
||||
@Suppress("DEPRECATION")
|
||||
vibrator.vibrate(longArrayOf(0, 40, 60, 40, 40, 80), -1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user