diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt index 5c0ea429..0ca73f91 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/extensions/Context.kt @@ -33,6 +33,9 @@ import com.simplemobiletools.clock.receivers.HideTimerReceiver import com.simplemobiletools.clock.services.SnoozeService import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.text.SimpleDateFormat import java.util.* import kotlin.math.pow @@ -266,6 +269,44 @@ fun Context.getNextAlarm(): String { return "$dayOfWeek $formatted" } +suspend fun Context.getClosestEnabledAlarmString(): String = withContext(Dispatchers.IO) { + val enabledAlarms = dbHelper.getEnabledAlarms() + val nextAlarmList = enabledAlarms + .mapNotNull { getTimeUntilNextAlarm(it.timeInMinutes, it.days) } + + if (nextAlarmList.isEmpty()) { + return@withContext "" + } + + var closestAlarmTime = Int.MAX_VALUE + nextAlarmList.forEach { time -> + if (time < closestAlarmTime) { + closestAlarmTime = time + } + } + + if (closestAlarmTime == Int.MAX_VALUE) { + return@withContext "" + } + + val calendar = Calendar.getInstance().apply { firstDayOfWeek = Calendar.MONDAY } + calendar.add(Calendar.MINUTE, closestAlarmTime) + var dayOfWeekIndex = calendar.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY + if (dayOfWeekIndex < 0) { // Adjust for Calendar.MONDAY being 2 + dayOfWeekIndex += 7 + } + + val dayOfWeek = resources.getStringArray(R.array.week_days_short)[dayOfWeekIndex] + val pattern = if (DateFormat.is24HourFormat(this@getClosestEnabledAlarmString)) { + "HH:mm" + } else { + "h:mm a" + } + + val formattedTime = SimpleDateFormat(pattern, Locale.getDefault()).format(calendar.time) + return@withContext "$dayOfWeek $formattedTime" +} + fun Context.rescheduleEnabledAlarms() { dbHelper.getEnabledAlarms().forEach { if (it.days != TODAY_BIT || it.timeInMinutes > getCurrentDayMinutes()) { diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/fragments/ClockFragment.kt b/app/src/main/kotlin/com/simplemobiletools/clock/fragments/ClockFragment.kt index 7419a7df..0bfa1b8c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/fragments/ClockFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/fragments/ClockFragment.kt @@ -7,6 +7,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope import com.simplemobiletools.clock.R import com.simplemobiletools.clock.activities.SimpleActivity import com.simplemobiletools.clock.adapters.TimeZonesAdapter @@ -20,6 +21,8 @@ import com.simplemobiletools.commons.extensions.getProperTextColor import com.simplemobiletools.commons.extensions.updateTextColors import kotlinx.android.synthetic.main.fragment_clock.* import kotlinx.android.synthetic.main.fragment_clock.view.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import java.util.* class ClockFragment : Fragment() { @@ -113,10 +116,12 @@ class ClockFragment : Fragment() { fun updateAlarm() { view.apply { - val nextAlarm = requireContext().getNextAlarm() - clock_alarm.beVisibleIf(nextAlarm.isNotEmpty()) - clock_alarm.text = nextAlarm - clock_alarm.colorCompoundDrawable(requireContext().getProperTextColor()) + lifecycleScope.launch { + val nextAlarm = requireContext().getClosestEnabledAlarmString() + clock_alarm.beVisibleIf(nextAlarm.isNotEmpty()) + clock_alarm.text = nextAlarm + clock_alarm.colorCompoundDrawable(requireContext().getProperTextColor()) + } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt index 1ab0759d..c9894afe 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt @@ -193,3 +193,43 @@ fun getAllTimeZones() = arrayListOf( MyTimeZone(88, "GMT+13:00 Auckland", "Pacific/Auckland"), 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 + + var minTimeDifferenceInMinutes = Int.MAX_VALUE + + 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 if (minTimeDifferenceInMinutes != Int.MAX_VALUE) { + minTimeDifferenceInMinutes + } else { + null + } +} + +fun isAlarmEnabledForDay(day: Int, alarmDays: Int): Boolean { + return ((alarmDays shr day) and 1) == 1 +} + +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) + } +} +