1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 package com.android.deskclock
17 
18 import android.content.Context
19 import android.text.format.DateFormat
20 import android.text.format.DateUtils
21 import android.view.View
22 import android.widget.Toast
23 import androidx.annotation.VisibleForTesting
24 
25 import com.android.deskclock.provider.AlarmInstance
26 import com.android.deskclock.widget.toast.SnackbarManager
27 import com.android.deskclock.widget.toast.ToastManager
28 
29 import com.google.android.material.snackbar.Snackbar
30 
31 import java.util.Calendar
32 import java.util.Locale
33 
34 /**
35  * Static utility methods for Alarms.
36  */
37 object AlarmUtils {
38     @JvmStatic
getFormattedTimenull39     fun getFormattedTime(context: Context, time: Calendar): String {
40         val skeleton = if (DateFormat.is24HourFormat(context)) "EHm" else "Ehma"
41         val pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton)
42         return DateFormat.format(pattern, time) as String
43     }
44 
45     @JvmStatic
getFormattedTimenull46     fun getFormattedTime(context: Context, timeInMillis: Long): String {
47         val c = Calendar.getInstance()
48         c.timeInMillis = timeInMillis
49         return getFormattedTime(context, c)
50     }
51 
52     @JvmStatic
getAlarmTextnull53     fun getAlarmText(context: Context, instance: AlarmInstance, includeLabel: Boolean): String {
54         val alarmTimeStr: String = getFormattedTime(context, instance.alarmTime)
55         return if (instance.mLabel!!.isEmpty() || !includeLabel) {
56             alarmTimeStr
57         } else {
58             alarmTimeStr + " - " + instance.mLabel
59         }
60     }
61 
62     /**
63      * format "Alarm set for 2 days, 7 hours, and 53 minutes from now."
64      */
65     @VisibleForTesting
formatElapsedTimeUntilAlarmnull66     fun formatElapsedTimeUntilAlarm(context: Context, delta: Long): String {
67         // If the alarm will ring within 60 seconds, just report "less than a minute."
68         var variableDelta = delta
69         val formats = context.resources.getStringArray(R.array.alarm_set)
70         if (variableDelta < DateUtils.MINUTE_IN_MILLIS) {
71             return formats[0]
72         }
73 
74         // Otherwise, format the remaining time until the alarm rings.
75 
76         // Round delta upwards to the nearest whole minute. (e.g. 7m 58s -> 8m)
77         val remainder = variableDelta % DateUtils.MINUTE_IN_MILLIS
78         variableDelta += if (remainder == 0L) 0 else DateUtils.MINUTE_IN_MILLIS - remainder
79         var hours = variableDelta.toInt() / (1000 * 60 * 60)
80         val minutes = variableDelta.toInt() / (1000 * 60) % 60
81         val days = hours / 24
82         hours %= 24
83 
84         val daySeq = Utils.getNumberFormattedQuantityString(context, R.plurals.days, days)
85         val minSeq = Utils.getNumberFormattedQuantityString(context, R.plurals.minutes, minutes)
86         val hourSeq = Utils.getNumberFormattedQuantityString(context, R.plurals.hours, hours)
87 
88         val showDays = days > 0
89         val showHours = hours > 0
90         val showMinutes = minutes > 0
91 
92         // Compute the index of the most appropriate time format based on the time delta.
93         val index = ((if (showDays) 1 else 0)
94                 or (if (showHours) 2 else 0)
95                 or (if (showMinutes) 4 else 0))
96 
97         return String.format(formats[index], daySeq, hourSeq, minSeq)
98     }
99 
100     @JvmStatic
popAlarmSetToastnull101     fun popAlarmSetToast(context: Context, alarmTime: Long) {
102         val alarmTimeDelta = alarmTime - System.currentTimeMillis()
103         val text = formatElapsedTimeUntilAlarm(context, alarmTimeDelta)
104         val toast = Toast.makeText(context, text, Toast.LENGTH_LONG)
105         ToastManager.setToast(toast)
106         toast.show()
107     }
108 
109     @JvmStatic
popAlarmSetSnackbarnull110     fun popAlarmSetSnackbar(snackbarAnchor: View, alarmTime: Long) {
111         val alarmTimeDelta = alarmTime - System.currentTimeMillis()
112         val text = formatElapsedTimeUntilAlarm(
113                 snackbarAnchor.context, alarmTimeDelta)
114         SnackbarManager.show(Snackbar.make(snackbarAnchor, text, Snackbar.LENGTH_SHORT))
115         snackbarAnchor.announceForAccessibility(text)
116     }
117 }