blob: 975a8957c6fc22c69d1e69e52bb9b8912afb32ad [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.deskclock.alarms
import android.app.Fragment
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Vibrator
import com.android.deskclock.AlarmClockFragment
import com.android.deskclock.LabelDialogFragment
import com.android.deskclock.LogUtils
import com.android.deskclock.R
import com.android.deskclock.alarms.dataadapter.AlarmItemHolder
import com.android.deskclock.data.DataModel
import com.android.deskclock.data.Weekdays
import com.android.deskclock.events.Events
import com.android.deskclock.provider.Alarm
import com.android.deskclock.provider.AlarmInstance
import com.android.deskclock.provider.ClockContract.InstancesColumns
import com.android.deskclock.ringtone.RingtonePickerActivity
import java.util.Calendar
/**
* Click handler for an alarm time item.
*/
// TODO(b/157255731) Replace deprecated Fragment related calls with AndroidX equivalent
class AlarmTimeClickHandler(
private val mFragment: Fragment,
savedState: Bundle?,
private val mAlarmUpdateHandler: AlarmUpdateHandler,
private val mScrollHandler: ScrollHandler
) {
private val mContext: Context = mFragment.getActivity().getApplicationContext()
private var mSelectedAlarm: Alarm? = null
private var mPreviousDaysOfWeekMap: Bundle? = null
init {
if (savedState != null) {
mPreviousDaysOfWeekMap = savedState.getBundle(KEY_PREVIOUS_DAY_MAP)
}
if (mPreviousDaysOfWeekMap == null) {
mPreviousDaysOfWeekMap = Bundle()
}
}
fun setSelectedAlarm(selectedAlarm: Alarm?) {
mSelectedAlarm = selectedAlarm
}
fun saveInstance(outState: Bundle) {
outState.putBundle(KEY_PREVIOUS_DAY_MAP, mPreviousDaysOfWeekMap)
}
fun setAlarmEnabled(alarm: Alarm, newState: Boolean) {
if (newState != alarm.enabled) {
alarm.enabled = newState
Events.sendAlarmEvent(if (newState) R.string.action_enable else R.string.action_disable,
R.string.label_deskclock)
mAlarmUpdateHandler.asyncUpdateAlarm(alarm, alarm.enabled, minorUpdate = false)
LOGGER.d("Updating alarm enabled state to $newState")
}
}
fun setAlarmVibrationEnabled(alarm: Alarm, newState: Boolean) {
if (newState != alarm.vibrate) {
alarm.vibrate = newState
Events.sendAlarmEvent(R.string.action_toggle_vibrate, R.string.label_deskclock)
mAlarmUpdateHandler.asyncUpdateAlarm(alarm, popToast = false, minorUpdate = true)
LOGGER.d("Updating vibrate state to $newState")
if (newState) {
// Buzz the vibrator to preview the alarm firing behavior.
val v: Vibrator = mContext.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (v.hasVibrator()) {
v.vibrate(300)
}
}
}
}
fun setAlarmRepeatEnabled(alarm: Alarm, isEnabled: Boolean) {
val now = Calendar.getInstance()
val oldNextAlarmTime = alarm.getNextAlarmTime(now)
val alarmId = alarm.id.toString()
if (isEnabled) {
// Set all previously set days
// or
// Set all days if no previous.
val bitSet: Int = mPreviousDaysOfWeekMap!!.getInt(alarmId)
alarm.daysOfWeek = Weekdays.fromBits(bitSet)
if (!alarm.daysOfWeek.isRepeating) {
alarm.daysOfWeek = Weekdays.ALL
}
} else {
// Remember the set days in case the user wants it back.
val bitSet = alarm.daysOfWeek.bits
mPreviousDaysOfWeekMap!!.putInt(alarmId, bitSet)
// Remove all repeat days
alarm.daysOfWeek = Weekdays.NONE
}
// if the change altered the next scheduled alarm time, tell the user
val newNextAlarmTime = alarm.getNextAlarmTime(now)
val popupToast = oldNextAlarmTime != newNextAlarmTime
Events.sendAlarmEvent(R.string.action_toggle_repeat_days, R.string.label_deskclock)
mAlarmUpdateHandler.asyncUpdateAlarm(alarm, popupToast, minorUpdate = false)
}
fun setDayOfWeekEnabled(alarm: Alarm, checked: Boolean, index: Int) {
val now = Calendar.getInstance()
val oldNextAlarmTime = alarm.getNextAlarmTime(now)
val weekday = DataModel.getDataModel().weekdayOrder.calendarDays[index]
alarm.daysOfWeek = alarm.daysOfWeek.setBit(weekday, checked)
// if the change altered the next scheduled alarm time, tell the user
val newNextAlarmTime = alarm.getNextAlarmTime(now)
val popupToast = oldNextAlarmTime != newNextAlarmTime
mAlarmUpdateHandler.asyncUpdateAlarm(alarm, popupToast, minorUpdate = false)
}
fun onDeleteClicked(itemHolder: AlarmItemHolder) {
if (mFragment is AlarmClockFragment) {
(mFragment as AlarmClockFragment).removeItem(itemHolder)
}
val alarm = itemHolder.item
Events.sendAlarmEvent(R.string.action_delete, R.string.label_deskclock)
mAlarmUpdateHandler.asyncDeleteAlarm(alarm)
LOGGER.d("Deleting alarm.")
}
fun onClockClicked(alarm: Alarm) {
mSelectedAlarm = alarm
Events.sendAlarmEvent(R.string.action_set_time, R.string.label_deskclock)
TimePickerDialogFragment.show(mFragment, alarm.hour, alarm.minutes)
}
fun dismissAlarmInstance(alarmInstance: AlarmInstance) {
val dismissIntent: Intent = AlarmStateManager.createStateChangeIntent(
mContext, AlarmStateManager.ALARM_DISMISS_TAG, alarmInstance,
InstancesColumns.PREDISMISSED_STATE)
mContext.startService(dismissIntent)
mAlarmUpdateHandler.showPredismissToast(alarmInstance)
}
fun onRingtoneClicked(context: Context, alarm: Alarm?) {
mSelectedAlarm = alarm
Events.sendAlarmEvent(R.string.action_set_ringtone, R.string.label_deskclock)
val intent: Intent = RingtonePickerActivity.createAlarmRingtonePickerIntent(context, alarm)
context.startActivity(intent)
}
fun onEditLabelClicked(alarm: Alarm) {
Events.sendAlarmEvent(R.string.action_set_label, R.string.label_deskclock)
val fragment = LabelDialogFragment.newInstance(alarm, alarm.label, mFragment.getTag())
LabelDialogFragment.show(mFragment.getFragmentManager(), fragment)
}
fun onTimeSet(hourOfDay: Int, minute: Int) {
if (mSelectedAlarm == null) {
// If mSelectedAlarm is null then we're creating a new alarm.
val a = Alarm()
a.hour = hourOfDay
a.minutes = minute
a.enabled = true
mAlarmUpdateHandler.asyncAddAlarm(a)
} else {
mSelectedAlarm!!.hour = hourOfDay
mSelectedAlarm!!.minutes = minute
mSelectedAlarm!!.enabled = true
mScrollHandler.setSmoothScrollStableId(mSelectedAlarm!!.id)
mAlarmUpdateHandler
.asyncUpdateAlarm(mSelectedAlarm!!, popToast = true, minorUpdate = false)
mSelectedAlarm = null
}
}
companion object {
private val LOGGER = LogUtils.Logger("AlarmTimeClickHandler")
private const val KEY_PREVIOUS_DAY_MAP = "previousDayMap"
}
}