package com.suno.android.utils import android.content.Context import android.hardware.Sensor import android.hardware.SensorEvent import android.hardware.SensorEventListener import android.hardware.SensorManager import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.setValue private const val MAX_OFFSET_PX = 8f private const val SMOOTHING_FACTOR = 0.15f /** * Manages device motion sensor to provide parallax offsets for UI effects. * Uses the gravity sensor to track device tilt and provides real-time offset values. * Applies exponential smoothing for natural, fluid motion. */ class ParallaxMotionManager( context: Context, private val smoothingFactor: Float = SMOOTHING_FACTOR, ) : SensorEventListener { private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as? SensorManager private val accelerometer = sensorManager?.getDefaultSensor(Sensor.TYPE_GRAVITY) var offsetX: Float by mutableFloatStateOf(0f) private set var offsetY: Float by mutableFloatStateOf(0f) private set private var targetOffsetX: Float = 0f private var targetOffsetY: Float = 0f fun startUpdates() { accelerometer?.let { sensorManager?.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) } } fun stopUpdates() { sensorManager?.unregisterListener(this) } override fun onSensorChanged( event: SensorEvent?, ) { event?.let { if (it.sensor.type == Sensor.TYPE_GRAVITY) { // Use gravity to determine device tilt // x: -1 to 1 (left to right) // y: -1 to 1 (bottom to top) val x = it.values[0] val y = it.values[1] // Calculate target offsets (invert for natural parallax) targetOffsetX = -x * MAX_OFFSET_PX targetOffsetY = y * MAX_OFFSET_PX // Apply exponential smoothing for fluid motion // Lower smoothingFactor = more damping/smoother offsetX += (targetOffsetX - offsetX) * smoothingFactor offsetY += (targetOffsetY - offsetY) * smoothingFactor } } } override fun onAccuracyChanged( sensor: Sensor?, accuracy: Int, ) { // Not needed for this implementation } }