feat: add tactile haptic feedback to rosary prayer cards
All checks were successful
CI / update (push) Successful in 3m56s
All checks were successful
CI / update (push) Successful in 3m56s
Every prayer card now vibrates on tap — non-decade cards advance to the next section, decade cards increment the Ave Maria counter with auto-scroll at 10. Two profiles (bead vs card) give distinct tactile feel; the 10th bead fires the heavier card haptic to mark decade completion. Native Android path via AndroidBridge.forceVibrate uses VibrationAttributes USAGE_ACCESSIBILITY so vibration bypasses silent / Do-Not-Disturb inside the Tauri app. Browser falls back to the web-haptics npm package. Haptic fires on pointerdown with touch-action: manipulation for near-zero tap latency; state change stays on click so scroll gestures don't advance. - Remove CounterButton (whole card is now the tap target) - Replace emoji with Lucide BookOpen icon, restyle citation as an understated inline typographic link (no background chip) - Drop decade min-height leftover from the pre-auto-advance layout Bumps site to 1.27.0 and Tauri app to 0.5.0 (new Android capability).
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bocken"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<!-- AndroidTV support -->
|
||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||
|
||||
@@ -6,6 +6,10 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.VibrationAttributes
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.os.VibratorManager
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.webkit.JavascriptInterface
|
||||
import androidx.core.app.ActivityCompat
|
||||
@@ -100,6 +104,36 @@ class AndroidBridge(private val context: Context) {
|
||||
return LocationForegroundService.getIntervalState()
|
||||
}
|
||||
|
||||
/**
|
||||
* Force-vibrate bypassing silent/DND by using USAGE_ACCESSIBILITY attributes.
|
||||
* Why: default web Vibration API uses USAGE_TOUCH which Android silences.
|
||||
*/
|
||||
@JavascriptInterface
|
||||
fun forceVibrate(durationMs: Long, intensityPct: Int) {
|
||||
val vibrator: Vibrator? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
(context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as? VibratorManager)?.defaultVibrator
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator
|
||||
}
|
||||
if (vibrator?.hasVibrator() != true) return
|
||||
|
||||
val amplitude = (intensityPct.coerceIn(1, 100) * 255 / 100).coerceAtLeast(1)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val effect = VibrationEffect.createOneShot(durationMs, amplitude)
|
||||
val attrs = VibrationAttributes.Builder()
|
||||
.setUsage(VibrationAttributes.USAGE_ACCESSIBILITY)
|
||||
.build()
|
||||
vibrator.vibrate(effect, attrs)
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(durationMs, amplitude))
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
vibrator.vibrate(durationMs)
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if at least one TTS engine is installed on the device. */
|
||||
@JavascriptInterface
|
||||
fun hasTtsEngine(): Boolean {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"productName": "Bocken",
|
||||
"identifier": "org.bocken.app",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"build": {
|
||||
"devUrl": "http://192.168.1.4:5173",
|
||||
"frontendDist": "https://bocken.org"
|
||||
|
||||
Reference in New Issue
Block a user