Fix various issues regarding Notification Profile scheduling.
- Timezone conversion when detecting scheduled profile - Not automatically enabling a scheduled profile on creation regardless of when other profiles were enabled/disabled
This commit is contained in:
parent
372b0d9f2b
commit
a8a104242a
11 changed files with 126 additions and 104 deletions
|
@ -1,10 +1,10 @@
|
|||
package org.thoughtcrime.securesms.components.settings.app.notifications.manual
|
||||
|
||||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
||||
import java.util.Calendar
|
||||
import java.time.LocalDateTime
|
||||
|
||||
data class NotificationProfileSelectionState(
|
||||
val notificationProfiles: List<NotificationProfile> = listOf(),
|
||||
val expandedId: Long = -1L,
|
||||
val timeSlotB: Calendar
|
||||
val timeSlotB: LocalDateTime
|
||||
)
|
||||
|
|
|
@ -9,8 +9,10 @@ import io.reactivex.rxjava3.kotlin.plusAssign
|
|||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.profiles.NotificationProfilesRepository
|
||||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
||||
import org.thoughtcrime.securesms.util.isBetween
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
import java.util.Calendar
|
||||
import org.thoughtcrime.securesms.util.toMillis
|
||||
import java.time.LocalDateTime
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class NotificationProfileSelectionViewModel(private val repository: NotificationProfilesRepository) : ViewModel() {
|
||||
|
@ -53,29 +55,24 @@ class NotificationProfileSelectionViewModel(private val repository: Notification
|
|||
.subscribe()
|
||||
}
|
||||
|
||||
fun enableUntil(profile: NotificationProfile, calendar: Calendar) {
|
||||
disposables += repository.manuallyEnableProfileForDuration(profile.id, calendar.timeInMillis)
|
||||
fun enableUntil(profile: NotificationProfile, enableUntil: LocalDateTime) {
|
||||
disposables += repository.manuallyEnableProfileForDuration(profile.id, enableUntil.toMillis())
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun getTimeSlotB(): Calendar {
|
||||
val now = Calendar.getInstance()
|
||||
val sixPm = Calendar.getInstance()
|
||||
val eightAm = Calendar.getInstance()
|
||||
@Suppress("CascadeIf")
|
||||
private fun getTimeSlotB(): LocalDateTime {
|
||||
val now = LocalDateTime.now()
|
||||
val sixPm = now.withHour(18).withMinute(0).withSecond(0)
|
||||
val eightAm = now.withHour(8).withMinute(0).withSecond(0)
|
||||
|
||||
sixPm.set(Calendar.HOUR_OF_DAY, 18)
|
||||
sixPm.set(Calendar.MINUTE, 0)
|
||||
sixPm.set(Calendar.SECOND, 0)
|
||||
|
||||
eightAm.set(Calendar.HOUR_OF_DAY, 8)
|
||||
eightAm.set(Calendar.MINUTE, 0)
|
||||
eightAm.set(Calendar.SECOND, 0)
|
||||
|
||||
return if (now.before(sixPm) && (now.after(eightAm) || now == eightAm)) {
|
||||
return if (now.isBetween(eightAm, sixPm)) {
|
||||
sixPm
|
||||
} else {
|
||||
} else if (now.isBefore(eightAm)) {
|
||||
eightAm
|
||||
} else {
|
||||
eightAm.plusDays(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ import org.thoughtcrime.securesms.components.emoji.EmojiImageView
|
|||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
||||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.MappingViewHolder
|
||||
import org.thoughtcrime.securesms.util.formatHours
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
|
||||
/**
|
||||
* Notification Profile selection preference.
|
||||
|
@ -34,10 +34,10 @@ object NotificationProfileSelection {
|
|||
override val summary: DSLSettingsText,
|
||||
val notificationProfile: NotificationProfile,
|
||||
val isExpanded: Boolean,
|
||||
val timeSlotB: Calendar,
|
||||
val timeSlotB: LocalDateTime,
|
||||
val onRowClick: (NotificationProfile) -> Unit,
|
||||
val onTimeSlotAClick: (NotificationProfile) -> Unit,
|
||||
val onTimeSlotBClick: (NotificationProfile, Calendar) -> Unit,
|
||||
val onTimeSlotBClick: (NotificationProfile, LocalDateTime) -> Unit,
|
||||
val onViewSettingsClick: (NotificationProfile) -> Unit,
|
||||
val onToggleClick: (NotificationProfile) -> Unit
|
||||
) : PreferenceModel<Entry>() {
|
||||
|
@ -87,7 +87,7 @@ object NotificationProfileSelection {
|
|||
expansion.visible = model.isExpanded
|
||||
timeSlotB.text = context.getString(
|
||||
R.string.NotificationProfileSelection__until_s,
|
||||
DateUtils.getTimeString(context, Locale.getDefault(), model.timeSlotB.timeInMillis)
|
||||
LocalTime.from(model.timeSlotB).formatHours()
|
||||
)
|
||||
|
||||
if (TOGGLE_EXPANSION in payload || UPDATE_TIMESLOT in payload) {
|
||||
|
@ -107,7 +107,7 @@ object NotificationProfileSelection {
|
|||
|
||||
timeSlotB.text = context.getString(
|
||||
R.string.NotificationProfileSelection__until_s,
|
||||
DateUtils.getTimeString(context, Locale.getDefault(), model.timeSlotB.timeInMillis)
|
||||
LocalTime.from(model.timeSlotB).formatHours()
|
||||
)
|
||||
|
||||
itemView.isSelected = model.isOn
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.time.format.DateTimeFormatter
|
|||
*/
|
||||
class EditNotificationProfileScheduleFragment : LoggingFragment(R.layout.fragment_edit_notification_profile_schedule) {
|
||||
|
||||
private val viewModel: EditNotificationProfileScheduleViewModel by viewModels(factoryProducer = { EditNotificationProfileScheduleViewModel.Factory(profileId) })
|
||||
private val viewModel: EditNotificationProfileScheduleViewModel by viewModels(factoryProducer = { EditNotificationProfileScheduleViewModel.Factory(profileId, createMode) })
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
private val profileId: Long by lazy { EditNotificationProfileScheduleFragmentArgs.fromBundle(requireArguments()).profileId }
|
||||
|
|
|
@ -17,7 +17,8 @@ import java.time.DayOfWeek
|
|||
* from the database and into the [scheduleSubject] allowing the safe use of !! with [schedule].
|
||||
*/
|
||||
class EditNotificationProfileScheduleViewModel(
|
||||
profileId: Long,
|
||||
private val profileId: Long,
|
||||
private val createMode: Boolean,
|
||||
private val repository: NotificationProfilesRepository
|
||||
) : ViewModel() {
|
||||
|
||||
|
@ -72,14 +73,23 @@ class EditNotificationProfileScheduleViewModel(
|
|||
} else if (createMode && !schedule.enabled) {
|
||||
Single.just(SaveScheduleResult.Success)
|
||||
} else {
|
||||
repository.updateSchedule(schedule).toSingle { SaveScheduleResult.Success }
|
||||
repository.updateSchedule(schedule)
|
||||
.toSingleDefault(SaveScheduleResult.Success)
|
||||
.flatMap { r ->
|
||||
if (createMode && schedule.enabled && schedule.coversTime(System.currentTimeMillis())) {
|
||||
repository.manuallyToggleProfile(profileId, schedule)
|
||||
.toSingleDefault(r)
|
||||
} else {
|
||||
Single.just(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
class Factory(private val profileId: Long) : ViewModelProvider.Factory {
|
||||
class Factory(private val profileId: Long, private val createMode: Boolean) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return modelClass.cast(EditNotificationProfileScheduleViewModel(profileId, NotificationProfilesRepository()))!!
|
||||
return modelClass.cast(EditNotificationProfileScheduleViewModel(profileId, createMode, NotificationProfilesRepository()))!!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,19 +96,23 @@ class NotificationProfilesRepository {
|
|||
}
|
||||
|
||||
fun manuallyToggleProfile(profile: NotificationProfile, now: Long = System.currentTimeMillis()): Completable {
|
||||
return manuallyToggleProfile(profile.id, profile.schedule, now)
|
||||
}
|
||||
|
||||
fun manuallyToggleProfile(profileId: Long, schedule: NotificationProfileSchedule, now: Long = System.currentTimeMillis()): Completable {
|
||||
return Completable.fromAction {
|
||||
val profiles = database.getProfiles()
|
||||
val activeProfile = NotificationProfiles.getActiveProfile(profiles, now)
|
||||
|
||||
if (profile.id == activeProfile?.id) {
|
||||
if (profileId == activeProfile?.id) {
|
||||
SignalStore.notificationProfileValues().manuallyEnabledProfile = 0
|
||||
SignalStore.notificationProfileValues().manuallyEnabledUntil = 0
|
||||
SignalStore.notificationProfileValues().manuallyDisabledAt = now
|
||||
SignalStore.notificationProfileValues().lastProfilePopup = 0
|
||||
SignalStore.notificationProfileValues().lastProfilePopupTime = 0
|
||||
} else {
|
||||
val inScheduledWindow = profile.schedule.isCurrentlyActive(now)
|
||||
SignalStore.notificationProfileValues().manuallyEnabledProfile = if (inScheduledWindow) 0 else profile.id
|
||||
val inScheduledWindow = schedule.isCurrentlyActive(now)
|
||||
SignalStore.notificationProfileValues().manuallyEnabledProfile = if (inScheduledWindow) 0 else profileId
|
||||
SignalStore.notificationProfileValues().manuallyEnabledUntil = if (inScheduledWindow) 0 else Long.MAX_VALUE
|
||||
SignalStore.notificationProfileValues().manuallyDisabledAt = if (inScheduledWindow) 0 else now
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.util.formatHours
|
|||
import org.thoughtcrime.securesms.util.toLocalDateTime
|
||||
import org.thoughtcrime.securesms.util.toLocalTime
|
||||
import org.thoughtcrime.securesms.util.toMillis
|
||||
import org.thoughtcrime.securesms.util.toOffset
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
|
||||
|
@ -26,7 +27,7 @@ object NotificationProfiles {
|
|||
val manualProfile: NotificationProfile? = profiles.firstOrNull { it.id == storeValues.manuallyEnabledProfile }
|
||||
|
||||
val scheduledProfile: NotificationProfile? = profiles.sortedDescending().filter { it.schedule.isCurrentlyActive(now, zoneId) }.firstOrNull { profile ->
|
||||
profile.schedule.startDateTime(localNow).toMillis() > storeValues.manuallyDisabledAt
|
||||
profile.schedule.startDateTime(localNow).toMillis(zoneId.toOffset()) > storeValues.manuallyDisabledAt
|
||||
}
|
||||
|
||||
if (manualProfile == null || scheduledProfile == null) {
|
||||
|
|
|
@ -3,17 +3,25 @@ package org.thoughtcrime.securesms.util
|
|||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Given a [ZoneId] return the time offset as a [ZoneOffset].
|
||||
*/
|
||||
fun ZoneId.toOffset(): ZoneOffset {
|
||||
return OffsetDateTime.now(this).offset
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert [LocalDateTime] to be same as [System.currentTimeMillis]
|
||||
*/
|
||||
fun LocalDateTime.toMillis(): Long {
|
||||
return TimeUnit.SECONDS.toMillis(toEpochSecond(ZoneOffset.UTC))
|
||||
fun LocalDateTime.toMillis(zoneOffset: ZoneOffset = ZoneId.systemDefault().toOffset()): Long {
|
||||
return TimeUnit.SECONDS.toMillis(toEpochSecond(zoneOffset))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -411,7 +411,7 @@
|
|||
</plurals>
|
||||
|
||||
<!-- Show in conversation list overflow menu to open selection bottom sheet -->
|
||||
<string name="ConversationListFragment__notification_profile">Notification Profile</string>
|
||||
<string name="ConversationListFragment__notification_profile">Notification profile</string>
|
||||
<!-- Tooltip shown after you have created your first notification profile -->
|
||||
<string name="ConversationListFragment__turn_your_notification_profile_on_or_off_here">Turn your notification profile on or off here.</string>
|
||||
<!-- Message shown in top toast to indicate the named profile is on -->
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.junit.Test
|
|||
import org.thoughtcrime.securesms.util.toMillis
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.util.TimeZone
|
||||
|
||||
class NotificationProfileScheduleTest {
|
||||
|
@ -37,105 +38,105 @@ class NotificationProfileScheduleTest {
|
|||
fun `when time is within enabled schedule 9am to 5pm then return true`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 900, end = 1700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.plusHours(1).toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.plusHours(1).toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when time is outside enabled schedule 9am to 5pm then return false`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 900, end = 1700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
|
||||
assertFalse(schedule.isCurrentlyActive(sunday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when time is inside enabled with day wrapping schedule 10pm to 2am then return true`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 2100, end = 200, daysEnabled = setOf(DayOfWeek.MONDAY))
|
||||
|
||||
assertTrue(schedule.isCurrentlyActive(monday10pm.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday1am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(monday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday1am.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when time is outside enabled with day wrapping schedule 10pm to 2am then return false`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 2100, end = 200, daysEnabled = setOf(DayOfWeek.MONDAY))
|
||||
|
||||
assertFalse(schedule.isCurrentlyActive(sunday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday10pm.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when time is inside enabled schedule 12am to 10am then return false`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 0, end = 1000, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
|
||||
assertTrue(schedule.isCurrentlyActive(sunday0am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday1am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when time is inside enabled schedule 12am to 12am then return false`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 0, end = 2400, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
|
||||
assertTrue(schedule.isCurrentlyActive(sunday0am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday1am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday10pm.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday10pm.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when time is outside enabled schedule 12am to 12am then return false`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 0, end = 2400, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
|
||||
assertFalse(schedule.isCurrentlyActive(monday0am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday10pm.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when enabled schedule 12am to 12am for all days then return true`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = true, start = 0, end = 2400, daysEnabled = DayOfWeek.values().toSet())
|
||||
|
||||
assertTrue(schedule.isCurrentlyActive(sunday0am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday1am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday10pm.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(monday0am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(monday1am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(monday9am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(monday10pm.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday1am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday9am.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday10pm.toMillis()))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(sunday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(monday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(monday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(monday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(monday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertTrue(schedule.isCurrentlyActive(tuesday10pm.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when disabled schedule 12am to 12am for all days then return false`() {
|
||||
val schedule = NotificationProfileSchedule(id = 1L, enabled = false, start = 0, end = 2400, daysEnabled = DayOfWeek.values().toSet())
|
||||
|
||||
assertFalse(schedule.isCurrentlyActive(sunday0am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday0am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(monday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday1am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday10pm.toMillis()))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(sunday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday0am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(monday10pm.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday1am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday9am.toMillis(ZoneOffset.UTC)))
|
||||
assertFalse(schedule.isCurrentlyActive(tuesday10pm.toMillis(ZoneOffset.UTC)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.util.toMillis
|
|||
import java.time.DayOfWeek
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(manifest = Config.NONE, application = Application::class)
|
||||
|
@ -69,30 +70,30 @@ class NotificationProfilesTest {
|
|||
fun `when first is scheduled and second is not manually enabled and now is within schedule return first`() {
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule), second)
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(), utc), `is`(profiles[0]))
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(ZoneOffset.UTC), utc), `is`(profiles[0]))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when first is scheduled and second is manually enabled forever within first's schedule then return second`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, second.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule), second)
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(), utc), `is`(profiles[1]))
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(ZoneOffset.UTC), utc), `is`(profiles[1]))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when first is scheduled and second is manually enabled forever before first's schedule start then return first`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, second.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 900, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule), second)
|
||||
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday930am.toMillis(), utc), `is`(profiles[0]))
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday930am.toMillis(ZoneOffset.UTC), utc), `is`(profiles[0]))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,41 +102,41 @@ class NotificationProfilesTest {
|
|||
val secondSchedule = NotificationProfileSchedule(id = 4L, true, start = 800, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = firstSchedule), second.copy(schedule = secondSchedule))
|
||||
|
||||
assertThat("active profile is second", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(), utc), `is`(profiles[1]))
|
||||
assertThat("active profile is second", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(ZoneOffset.UTC), utc), `is`(profiles[1]))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when first and second have overlapping schedules and first is created before second and first is manually enabled within overlapping schedule then return first`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, Long.MAX_VALUE)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
|
||||
val firstSchedule = NotificationProfileSchedule(id = 3L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val secondSchedule = NotificationProfileSchedule(id = 4L, true, start = 700, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = firstSchedule), second.copy(schedule = secondSchedule))
|
||||
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(), utc), `is`(profiles[0]))
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(ZoneOffset.UTC), utc), `is`(profiles[0]))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when profile is manually enabled for set time after schedule end and now is after schedule end but before manual then return profile`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday930am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday930am.toMillis(ZoneOffset.UTC))
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, end = 845, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule))
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(), utc), `is`(profiles[0]))
|
||||
assertThat("active profile is first", NotificationProfiles.getActiveProfile(profiles, sunday9am.toMillis(ZoneOffset.UTC), utc), `is`(profiles[0]))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when profile is manually enabled for set time before schedule end and now is after manual but before schedule end then return null`() {
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_PROFILE, first.id)
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday9am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis())
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_ENABLED_UNTIL, sunday9am.toMillis(ZoneOffset.UTC))
|
||||
signalStore.dataSet.putLong(NotificationProfileValues.KEY_MANUALLY_DISABLED_AT, sunday830am.toMillis(ZoneOffset.UTC))
|
||||
|
||||
val schedule = NotificationProfileSchedule(id = 3L, true, start = 700, end = 1000, daysEnabled = setOf(DayOfWeek.SUNDAY))
|
||||
val profiles = listOf(first.copy(schedule = schedule))
|
||||
assertThat("active profile is null", NotificationProfiles.getActiveProfile(profiles, sunday930am.toMillis(), utc), nullValue())
|
||||
assertThat("active profile is null", NotificationProfiles.getActiveProfile(profiles, sunday930am.toMillis(ZoneOffset.UTC), utc), nullValue())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue