diff --git a/app/src/main/kotlin/org/fossify/clock/activities/ReminderActivity.kt b/app/src/main/kotlin/org/fossify/clock/activities/ReminderActivity.kt index b1f01ee7..b9382f46 100644 --- a/app/src/main/kotlin/org/fossify/clock/activities/ReminderActivity.kt +++ b/app/src/main/kotlin/org/fossify/clock/activities/ReminderActivity.kt @@ -23,6 +23,7 @@ import org.fossify.commons.helpers.MINUTE_SECONDS import org.fossify.commons.helpers.SILENT import org.fossify.commons.helpers.isOreoMr1Plus import org.fossify.commons.helpers.isOreoPlus +import java.util.Calendar class ReminderActivity : SimpleActivity() { companion object { @@ -267,23 +268,23 @@ class ReminderActivity : SimpleActivity() { private fun snoozeAlarm(overrideSnoozeDuration: Int? = null) { destroyEffects() if (overrideSnoozeDuration != null) { - setupAlarmClock(alarm!!, overrideSnoozeDuration * MINUTE_SECONDS) - wasAlarmSnoozed = true - finishActivity() + snoozeAlarm { add(Calendar.MINUTE, overrideSnoozeDuration) } } else if (config.useSameSnooze) { - setupAlarmClock(alarm!!, config.snoozeTime * MINUTE_SECONDS) - wasAlarmSnoozed = true - finishActivity() + snoozeAlarm { add(Calendar.MINUTE, config.snoozeTime) } } else { showPickSecondsDialog(config.snoozeTime * MINUTE_SECONDS, true, cancelCallback = { finishActivity() }) { config.snoozeTime = it / MINUTE_SECONDS - setupAlarmClock(alarm!!, it) - wasAlarmSnoozed = true - finishActivity() + snoozeAlarm { add(Calendar.SECOND, it) } } } } + private fun snoozeAlarm(block: Calendar.() -> Unit) { + setupAlarmClock(alarm!!, block.run { Calendar.getInstance() }) + wasAlarmSnoozed = true + finishActivity() + } + private fun finishActivity() { if (!wasAlarmSnoozed && alarm != null) { cancelAlarmClock(alarm!!) diff --git a/app/src/main/kotlin/org/fossify/clock/activities/SnoozeReminderActivity.kt b/app/src/main/kotlin/org/fossify/clock/activities/SnoozeReminderActivity.kt index 17f40d60..ab00a2f2 100644 --- a/app/src/main/kotlin/org/fossify/clock/activities/SnoozeReminderActivity.kt +++ b/app/src/main/kotlin/org/fossify/clock/activities/SnoozeReminderActivity.kt @@ -9,6 +9,7 @@ import org.fossify.clock.extensions.setupAlarmClock import org.fossify.clock.helpers.ALARM_ID import org.fossify.commons.extensions.showPickSecondsDialog import org.fossify.commons.helpers.MINUTE_SECONDS +import java.util.Calendar class SnoozeReminderActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -18,7 +19,7 @@ class SnoozeReminderActivity : AppCompatActivity() { hideNotification(id) showPickSecondsDialog(config.snoozeTime * MINUTE_SECONDS, true, cancelCallback = { dialogCancelled() }) { config.snoozeTime = it / MINUTE_SECONDS - setupAlarmClock(alarm, it) + setupAlarmClock(alarm, Calendar.getInstance().apply { add(Calendar.SECOND, it) }) finishActivity() } } diff --git a/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt b/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt index 95057827..ca1ad4ff 100644 --- a/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt +++ b/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt @@ -100,40 +100,13 @@ fun Context.createNewTimer(): Timer { } fun Context.scheduleNextAlarm(alarm: Alarm, showToast: Boolean) { - val calendar = Calendar.getInstance() - calendar.firstDayOfWeek = Calendar.MONDAY - val currentTimeInMinutes = getCurrentDayMinutes() + val triggerTime = getTimeOfNextAlarm(alarm.timeInMinutes, alarm.days) ?: return + setupAlarmClock(alarm, triggerTime) - if (alarm.days == TODAY_BIT) { - val triggerInMinutes = alarm.timeInMinutes - currentTimeInMinutes - setupAlarmClock(alarm, triggerInMinutes * 60 - calendar.get(Calendar.SECOND)) - - if (showToast) { - showRemainingTimeMessage(triggerInMinutes) - } - } else if (alarm.days == TOMORROW_BIT) { - val triggerInMinutes = alarm.timeInMinutes - currentTimeInMinutes + DAY_MINUTES - setupAlarmClock(alarm, triggerInMinutes * 60 - calendar.get(Calendar.SECOND)) - - if (showToast) { - showRemainingTimeMessage(triggerInMinutes) - } - } else { - for (i in 0..7) { - val currentDay = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7 - val isCorrectDay = alarm.days and 2.0.pow(currentDay).toInt() != 0 - if (isCorrectDay && (alarm.timeInMinutes > currentTimeInMinutes || i > 0)) { - val triggerInMinutes = alarm.timeInMinutes - currentTimeInMinutes + (i * DAY_MINUTES) - setupAlarmClock(alarm, triggerInMinutes * 60 - calendar.get(Calendar.SECOND)) - - if (showToast) { - showRemainingTimeMessage(triggerInMinutes) - } - break - } else { - calendar.add(Calendar.DAY_OF_MONTH, 1) - } - } + if (showToast) { + val now = Calendar.getInstance() + val triggerInMillis = triggerTime.timeInMillis - now.timeInMillis + showRemainingTimeMessage((triggerInMillis / (1000 * 60)).toInt()) } } @@ -142,9 +115,10 @@ fun Context.showRemainingTimeMessage(totalMinutes: Int) { toast(fullString, Toast.LENGTH_LONG) } -fun Context.setupAlarmClock(alarm: Alarm, triggerInSeconds: Int) { +fun Context.setupAlarmClock(alarm: Alarm, triggerTime: Calendar) { val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager - val targetMS = System.currentTimeMillis() + triggerInSeconds * 1000 + + val targetMS = triggerTime.timeInMillis try { AlarmManagerCompat.setAlarmClock(alarmManager, targetMS, getOpenAlarmTabIntent(), getAlarmIntent(alarm)) @@ -277,27 +251,19 @@ fun Context.getClosestEnabledAlarmString(callback: (result: String) -> Unit) { return@getEnabledAlarms } + val now = Calendar.getInstance() val nextAlarmList = enabledAlarms - .mapNotNull { getTimeUntilNextAlarm(it.timeInMinutes, it.days) } + .mapNotNull { getTimeOfNextAlarm(it.timeInMinutes, it.days) } + .filter { it > now } - if (nextAlarmList.isEmpty()) { - callback("") - } + val closestAlarmTime = nextAlarmList.minOrNull() - var closestAlarmTime = Int.MAX_VALUE - nextAlarmList.forEach { time -> - if (time < closestAlarmTime) { - closestAlarmTime = time - } - } - - if (closestAlarmTime == Int.MAX_VALUE) { + if (closestAlarmTime == null) { callback("") + return@getEnabledAlarms } - val calendar = Calendar.getInstance().apply { firstDayOfWeek = Calendar.MONDAY } - calendar.add(Calendar.MINUTE, closestAlarmTime) - val dayOfWeekIndex = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7 + val dayOfWeekIndex = (closestAlarmTime.get(Calendar.DAY_OF_WEEK) + 5) % 7 val dayOfWeek = resources.getStringArray(org.fossify.commons.R.array.week_days_short)[dayOfWeekIndex] val pattern = if (DateFormat.is24HourFormat(this)) { "HH:mm" @@ -305,7 +271,7 @@ fun Context.getClosestEnabledAlarmString(callback: (result: String) -> Unit) { "h:mm a" } - val formattedTime = SimpleDateFormat(pattern, Locale.getDefault()).format(calendar.time) + val formattedTime = SimpleDateFormat(pattern, Locale.getDefault()).format(closestAlarmTime.time) callback("$dayOfWeek $formattedTime") } } diff --git a/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt b/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt index 99fd99c4..5cd47c57 100644 --- a/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt +++ b/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt @@ -111,14 +111,14 @@ fun formatTime(showSeconds: Boolean, use24HourFormat: Boolean, hours: Int, minut fun getTomorrowBit(): Int { val calendar = Calendar.getInstance() calendar.add(Calendar.DAY_OF_WEEK, 1) - val dayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7 - return 2.0.pow(dayOfWeek).toInt() + val day = calendar.get(Calendar.DAY_OF_WEEK) + return getBitForCalendarDay(day) } fun getTodayBit(): Int { val calendar = Calendar.getInstance() - val dayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7 - return 2.0.pow(dayOfWeek).toInt() + val day = calendar.get(Calendar.DAY_OF_WEEK) + return getBitForCalendarDay(day) } fun getBitForCalendarDay(day: Int): Int { @@ -222,39 +222,37 @@ fun getAllTimeZones() = arrayListOf( MyTimeZone(89, "GMT+13:00 Tongatapu", "Pacific/Tongatapu") ) -fun getTimeUntilNextAlarm(alarmTimeInMinutes: Int, days: Int): Int? { - val calendar = Calendar.getInstance() - calendar.firstDayOfWeek = Calendar.MONDAY - val currentTimeInMinutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE) - val currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY +fun getTimeOfNextAlarm(alarmTimeInMinutes: Int, days: Int): Calendar? { + val nextAlarmTime = Calendar.getInstance() + nextAlarmTime.firstDayOfWeek = Calendar.MONDAY + + val hour = alarmTimeInMinutes / 60 + val minute = alarmTimeInMinutes % 60 - var minTimeDifferenceInMinutes = Int.MAX_VALUE + nextAlarmTime.set(Calendar.HOUR_OF_DAY, hour) + nextAlarmTime.set(Calendar.MINUTE, minute) + nextAlarmTime.set(Calendar.SECOND, 0) + nextAlarmTime.set(Calendar.MILLISECOND, 0) - for (i in 0..6) { - val alarmDayOfWeek = (currentDayOfWeek + i) % 7 - if (isAlarmEnabledForDay(alarmDayOfWeek, days)) { - val timeDifferenceInMinutes = getTimeDifferenceInMinutes(currentTimeInMinutes, alarmTimeInMinutes, i) - if (timeDifferenceInMinutes < minTimeDifferenceInMinutes) { - minTimeDifferenceInMinutes = timeDifferenceInMinutes + return when (days) { + TODAY_BIT -> { + // do nothing, alarm is today + nextAlarmTime + } + TOMORROW_BIT -> { + nextAlarmTime.apply { add(Calendar.DAY_OF_MONTH, 1) } + } + else -> { + val now = Calendar.getInstance() + repeat(8) { + val currentDay = (nextAlarmTime.get(Calendar.DAY_OF_WEEK) + 5) % 7 + if (days.isBitSet(currentDay) && now < nextAlarmTime) { + return nextAlarmTime + } else { + nextAlarmTime.add(Calendar.DAY_OF_MONTH, 1) + } } + null } } - - return if (minTimeDifferenceInMinutes != Int.MAX_VALUE) { - minTimeDifferenceInMinutes - } else { - null - } -} - -fun isAlarmEnabledForDay(day: Int, alarmDays: Int) = alarmDays.isBitSet(day) - -fun getTimeDifferenceInMinutes(currentTimeInMinutes: Int, alarmTimeInMinutes: Int, daysUntilAlarm: Int): Int { - val minutesInADay = 24 * 60 - val minutesUntilAlarm = daysUntilAlarm * minutesInADay + alarmTimeInMinutes - return if (minutesUntilAlarm > currentTimeInMinutes) { - minutesUntilAlarm - currentTimeInMinutes - } else { - minutesInADay - (currentTimeInMinutes - minutesUntilAlarm) - } } diff --git a/app/src/main/kotlin/org/fossify/clock/services/SnoozeService.kt b/app/src/main/kotlin/org/fossify/clock/services/SnoozeService.kt index 9b4024b4..dfdaa94f 100644 --- a/app/src/main/kotlin/org/fossify/clock/services/SnoozeService.kt +++ b/app/src/main/kotlin/org/fossify/clock/services/SnoozeService.kt @@ -8,12 +8,13 @@ import org.fossify.clock.extensions.hideNotification import org.fossify.clock.extensions.setupAlarmClock import org.fossify.clock.helpers.ALARM_ID import org.fossify.commons.helpers.MINUTE_SECONDS +import java.util.Calendar class SnoozeService : IntentService("Snooze") { override fun onHandleIntent(intent: Intent?) { val id = intent!!.getIntExtra(ALARM_ID, -1) val alarm = dbHelper.getAlarmWithId(id) ?: return hideNotification(id) - setupAlarmClock(alarm, config.snoozeTime * MINUTE_SECONDS) + setupAlarmClock(alarm, Calendar.getInstance().apply { add(Calendar.MINUTE, config.snoozeTime) }) } }