1 /* 2 * Copyright (C) 2023 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 17 package com.android.systemui.qs.tiles.impl.alarm.domain 18 19 import android.content.res.Resources 20 import android.content.res.Resources.Theme 21 import com.android.systemui.common.shared.model.Icon 22 import com.android.systemui.dagger.qualifiers.Main 23 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper 24 import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel 25 import com.android.systemui.qs.tiles.viewmodel.QSTileConfig 26 import com.android.systemui.qs.tiles.viewmodel.QSTileState 27 import com.android.systemui.res.R 28 import com.android.systemui.util.time.SystemClock 29 import java.time.Instant 30 import java.time.LocalDateTime 31 import java.time.format.DateTimeFormatter 32 import java.util.TimeZone 33 import javax.inject.Inject 34 35 /** Maps [AlarmTileModel] to [QSTileState]. */ 36 class AlarmTileMapper 37 @Inject 38 constructor( 39 @Main private val resources: Resources, 40 private val theme: Theme, 41 private val clock: SystemClock, 42 ) : QSTileDataToStateMapper<AlarmTileModel> { 43 companion object { 44 val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a") 45 val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm") 46 val formatterDateOnly: DateTimeFormatter = DateTimeFormatter.ofPattern("E MMM d") 47 } mapnull48 override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState = 49 QSTileState.build(resources, theme, config.uiConfig) { 50 when (data) { 51 is AlarmTileModel.NextAlarmSet -> { 52 activationState = QSTileState.ActivationState.ACTIVE 53 54 val alarmDateTime = 55 LocalDateTime.ofInstant( 56 Instant.ofEpochMilli(data.alarmClockInfo.triggerTime), 57 TimeZone.getDefault().toZoneId() 58 ) 59 60 val nowDateTime = 61 LocalDateTime.ofInstant( 62 Instant.ofEpochMilli(clock.currentTimeMillis()), 63 TimeZone.getDefault().toZoneId() 64 ) 65 66 // Edge case: If it's 8:00:30 right now and alarm is requested for next week at 67 // 8:00:29, we still want to show the date. Same at nanosecond level. 68 val nextWeekThisTime = nowDateTime.plusWeeks(1).withSecond(0).withNano(0) 69 70 // is the alarm over a week away? 71 val shouldShowDateAndHideTime = alarmDateTime >= nextWeekThisTime 72 73 if (shouldShowDateAndHideTime) { 74 secondaryLabel = formatterDateOnly.format(alarmDateTime) 75 } else { 76 secondaryLabel = 77 if (data.is24HourFormat) formatter24Hour.format(alarmDateTime) 78 else formatter12Hour.format(alarmDateTime) 79 } 80 } 81 is AlarmTileModel.NoAlarmSet -> { 82 activationState = QSTileState.ActivationState.INACTIVE 83 secondaryLabel = resources.getString(R.string.qs_alarm_tile_no_alarm) 84 } 85 } 86 iconRes = R.drawable.ic_alarm 87 icon = { Icon.Loaded(resources.getDrawable(iconRes!!, theme), null) } 88 sideViewIcon = QSTileState.SideViewIcon.Chevron 89 contentDescription = label 90 supportedActions = setOf(QSTileState.UserAction.CLICK) 91 } 92 } 93