From 1f692044d2b9b035dae7d8d26778b7e9d648c5b4 Mon Sep 17 00:00:00 2001 From: yilsem Date: Thu, 8 Oct 2026 02:43:32 +0300 Subject: [PATCH] fix(cron): preserve chosen clock time across repeat changes --- .../ui/cron/SchedulePickerTest.kt | 22 +++++++++---------- .../hermescontrol/ui/cron/CronJobsScreen.kt | 6 +++-- .../ui/cron/ScheduleSelection.kt | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/androidTest/java/com/m57/hermescontrol/ui/cron/SchedulePickerTest.kt b/app/src/androidTest/java/com/m57/hermescontrol/ui/cron/SchedulePickerTest.kt index 27da0b53..0607e43b 100644 --- a/app/src/androidTest/java/com/m57/hermescontrol/ui/cron/SchedulePickerTest.kt +++ b/app/src/androidTest/java/com/m57/hermescontrol/ui/cron/SchedulePickerTest.kt @@ -1,7 +1,6 @@ package com.m57.hermescontrol.ui.cron import android.graphics.Bitmap -import android.content.res.Configuration import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -10,12 +9,10 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.getValue -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText @@ -34,13 +31,8 @@ class SchedulePickerTest { @Test fun repeatDropdownAndClockPreserveSchedule() { var schedule by mutableStateOf("59 23 * * *") - val baseContext = InstrumentationRegistry.getInstrumentation().targetContext - val configuration = Configuration(baseContext.resources.configuration).apply { - setLocale(java.util.Locale.forLanguageTag("tr-TR")) - } - val context = baseContext.createConfigurationContext(configuration) + val context = InstrumentationRegistry.getInstrumentation().targetContext compose.setContent { - CompositionLocalProvider(LocalContext provides context, LocalConfiguration provides configuration) { MaterialTheme { Surface { Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp)) { @@ -48,11 +40,11 @@ class SchedulePickerTest { } } } - } } fun text(id: Int) = context.getString(id) fun screenshot(name: String) { compose.waitForIdle() + android.os.SystemClock.sleep(500) val bitmap = InstrumentationRegistry.getInstrumentation().uiAutomation.takeScreenshot() File(context.getExternalFilesDir(null), "$name.png").outputStream().use { bitmap.compress(Bitmap.CompressFormat.PNG, 100, it) @@ -62,7 +54,7 @@ class SchedulePickerTest { compose.onNodeWithText("23:59").performClick() screenshot("schedule-clock-360") compose.onNodeWithText("59").performClick() - compose.onNodeWithText("55").performClick() + compose.onNode(hasContentDescription("55", substring = true)).performClick() compose.onNodeWithText(text(R.string.action_ok)).performClick() compose.runOnIdle { assertEquals("55 23 * * *", schedule) } compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick() @@ -71,6 +63,12 @@ class SchedulePickerTest { compose.runOnIdle { assertEquals("55 23 1 1 *", schedule) } screenshot("schedule-yearly-360") compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick() + compose.onAllNodesWithText(text(R.string.cron_repeat_hourly))[0].performClick() + compose.runOnIdle { assertEquals("55 * * * *", schedule) } + compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick() + compose.onAllNodesWithText(text(R.string.cron_schedule_mode_daily))[0].performClick() + compose.runOnIdle { assertEquals("55 23 * * *", schedule) } + compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick() compose.onAllNodesWithText(text(R.string.cron_repeat_minutely))[0].performClick() compose.runOnIdle { assertEquals("* * * * *", schedule) } } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt index f5718fe6..cee8840d 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt @@ -1004,8 +1004,8 @@ internal fun SchedulePickerSection( val parsed = remember(schedule) { parseSchedule(schedule) } var mode by remember(schedule) { mutableStateOf(parsed.mode) } - var hour by remember(schedule) { mutableStateOf(parsed.hour) } - var minute by remember(schedule) { mutableStateOf(parsed.minute) } + var hour by remember { mutableStateOf(parsed.hour) } + var minute by remember { mutableStateOf(parsed.minute) } var intervalCount by remember(schedule) { mutableStateOf(parsed.intervalCount) } var intervalUnit by remember(schedule) { mutableStateOf(parsed.intervalUnit) } var selectedDays by remember(schedule) { mutableStateOf(parsed.selectedDays) } @@ -1055,6 +1055,8 @@ internal fun SchedulePickerSection( } else { val fallback = parseSchedule(schedule) mode = fallback.mode + hour = fallback.hour + minute = fallback.minute } }, ) { diff --git a/app/src/main/java/com/m57/hermescontrol/ui/cron/ScheduleSelection.kt b/app/src/main/java/com/m57/hermescontrol/ui/cron/ScheduleSelection.kt index b2cba5c5..5c4bb54a 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/cron/ScheduleSelection.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/cron/ScheduleSelection.kt @@ -17,7 +17,7 @@ internal data class ParsedSchedule( val minute: Int = 0, val intervalCount: Int = 1, val intervalUnit: String = "h", - val selectedDays: Set = setOf(1, 2, 3, 4, 5), + val selectedDays: Set = setOf(1), val dayOfMonth: Int = 1, val month: Int = 1, val raw: String = "",