Simple-Clock/app/src/main/kotlin/com/simplemobiletools/clock/activities/ReminderActivity.kt

279 lines
10 KiB
Kotlin

package com.simplemobiletools.clock.activities
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.*
import android.view.MotionEvent
import android.view.WindowManager
import android.view.animation.AnimationUtils
import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.databinding.ActivityReminderBinding
import com.simplemobiletools.clock.extensions.*
import com.simplemobiletools.clock.helpers.ALARM_ID
import com.simplemobiletools.clock.helpers.getPassedSeconds
import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
class ReminderActivity : SimpleActivity() {
private val INCREASE_VOLUME_DELAY = 300L
private val increaseVolumeHandler = Handler()
private val maxReminderDurationHandler = Handler()
private val swipeGuideFadeHandler = Handler()
private val vibrationHandler = Handler(Looper.getMainLooper())
private var isAlarmReminder = false
private var didVibrate = false
private var wasAlarmSnoozed = false
private var alarm: Alarm? = null
private var audioManager: AudioManager? = null
private var mediaPlayer: MediaPlayer? = null
private var vibrator: Vibrator? = null
private var lastVolumeValue = 0.1f
private var dragDownX = 0f
private lateinit var binding: ActivityReminderBinding
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
binding = ActivityReminderBinding.inflate(layoutInflater)
setContentView(binding.root)
showOverLockscreen()
updateTextColors(binding.root)
updateStatusbarColor(getProperBackgroundColor())
val id = intent.getIntExtra(ALARM_ID, -1)
isAlarmReminder = id != -1
if (id != -1) {
alarm = dbHelper.getAlarmWithId(id) ?: return
}
val label = if (isAlarmReminder) {
if (alarm!!.label.isEmpty()) {
getString(com.simplemobiletools.commons.R.string.alarm)
} else {
alarm!!.label
}
} else {
getString(R.string.timer)
}
binding.reminderTitle.text = label
binding.reminderText.text = if (isAlarmReminder) getFormattedTime(getPassedSeconds(), false, false) else getString(R.string.time_expired)
val maxDuration = if (isAlarmReminder) config.alarmMaxReminderSecs else config.timerMaxReminderSecs
maxReminderDurationHandler.postDelayed({
finishActivity()
}, maxDuration * 1000L)
setupButtons()
setupEffects()
}
private fun setupButtons() {
if (isAlarmReminder) {
setupAlarmButtons()
} else {
setupTimerButtons()
}
}
@SuppressLint("ClickableViewAccessibility")
private fun setupAlarmButtons() {
binding.reminderStop.beGone()
binding.reminderDraggableBackground.startAnimation(AnimationUtils.loadAnimation(this, R.anim.pulsing_animation))
binding.reminderDraggableBackground.applyColorFilter(getProperPrimaryColor())
val textColor = getProperTextColor()
binding.reminderDismiss.applyColorFilter(textColor)
binding.reminderDraggable.applyColorFilter(textColor)
binding.reminderSnooze.applyColorFilter(textColor)
var minDragX = 0f
var maxDragX = 0f
var initialDraggableX = 0f
binding.reminderDismiss.onGlobalLayout {
minDragX = binding.reminderSnooze.left.toFloat()
maxDragX = binding.reminderDismiss.left.toFloat()
initialDraggableX = binding.reminderDraggable.left.toFloat()
}
binding.reminderDraggable.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
dragDownX = event.x
binding.reminderDraggableBackground.animate().alpha(0f)
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
dragDownX = 0f
if (!didVibrate) {
binding.reminderDraggable.animate().x(initialDraggableX).withEndAction {
binding.reminderDraggableBackground.animate().alpha(0.2f)
}
binding.reminderGuide.animate().alpha(1f).start()
swipeGuideFadeHandler.removeCallbacksAndMessages(null)
swipeGuideFadeHandler.postDelayed({
binding.reminderGuide.animate().alpha(0f).start()
}, 2000L)
}
}
MotionEvent.ACTION_MOVE -> {
binding.reminderDraggable.x = Math.min(maxDragX, Math.max(minDragX, event.rawX - dragDownX))
if (binding.reminderDraggable.x >= maxDragX - 50f) {
if (!didVibrate) {
binding.reminderDraggable.performHapticFeedback()
didVibrate = true
finishActivity()
}
if (isOreoPlus()) {
notificationManager.cancelAll()
}
} else if (binding.reminderDraggable.x <= minDragX + 50f) {
if (!didVibrate) {
binding.reminderDraggable.performHapticFeedback()
didVibrate = true
snoozeAlarm()
}
if (isOreoPlus()) {
notificationManager.cancelAll()
}
}
}
}
true
}
}
private fun setupTimerButtons() {
binding.reminderStop.background = resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, getProperPrimaryColor())
arrayOf(binding.reminderSnooze, binding.reminderDraggableBackground, binding.reminderDraggable, binding.reminderDismiss).forEach {
it.beGone()
}
binding.reminderStop.setOnClickListener {
finishActivity()
}
}
private fun setupEffects() {
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val maxVol = audioManager?.getStreamMaxVolume(AudioManager.STREAM_ALARM)?.toFloat() ?: 10f
if (!isAlarmReminder || !config.increaseVolumeGradually) {
lastVolumeValue = maxVol
}
val doVibrate = alarm?.vibrate ?: config.timerVibrate
if (doVibrate && isOreoPlus()) {
val pattern = LongArray(2) { 500 }
vibrationHandler.postDelayed({
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator?.vibrate(VibrationEffect.createWaveform(pattern, 0))
}, 500)
}
val soundUri = if (alarm != null) {
alarm!!.soundUri
} else {
config.timerSoundUri
}
if (soundUri != SILENT) {
try {
mediaPlayer = MediaPlayer().apply {
setAudioStreamType(AudioManager.STREAM_ALARM)
setDataSource(this@ReminderActivity, Uri.parse(soundUri))
setVolume(lastVolumeValue, lastVolumeValue)
isLooping = true
prepare()
start()
}
if (config.increaseVolumeGradually) {
scheduleVolumeIncrease(maxVol)
}
} catch (e: Exception) {
}
}
}
private fun scheduleVolumeIncrease(maxVolume: Float) {
increaseVolumeHandler.postDelayed({
lastVolumeValue = (lastVolumeValue + 0.1f).coerceAtMost(maxVolume)
audioManager?.setStreamVolume(AudioManager.STREAM_ALARM, lastVolumeValue.toInt(), 0)
scheduleVolumeIncrease(maxVolume)
}, INCREASE_VOLUME_DELAY)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
finishActivity()
}
override fun onDestroy() {
super.onDestroy()
increaseVolumeHandler.removeCallbacksAndMessages(null)
maxReminderDurationHandler.removeCallbacksAndMessages(null)
swipeGuideFadeHandler.removeCallbacksAndMessages(null)
vibrationHandler.removeCallbacksAndMessages(null)
destroyEffects()
}
private fun destroyEffects() {
mediaPlayer?.stop()
mediaPlayer?.release()
mediaPlayer = null
vibrator?.cancel()
vibrator = null
}
private fun snoozeAlarm() {
destroyEffects()
if (config.useSameSnooze) {
setupAlarmClock(alarm!!, config.snoozeTime * MINUTE_SECONDS)
wasAlarmSnoozed = true
finishActivity()
} else {
showPickSecondsDialog(config.snoozeTime * MINUTE_SECONDS, true, cancelCallback = { finishActivity() }) {
config.snoozeTime = it / MINUTE_SECONDS
setupAlarmClock(alarm!!, it)
wasAlarmSnoozed = true
finishActivity()
}
}
}
private fun finishActivity() {
if (!wasAlarmSnoozed && alarm != null && alarm!!.days > 0) {
scheduleNextAlarm(alarm!!, false)
}
destroyEffects()
finish()
overridePendingTransition(0, 0)
}
private fun showOverLockscreen() {
window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
)
if (isOreoMr1Plus()) {
setShowWhenLocked(true)
setTurnScreenOn(true)
}
}
}