From bf8a588020d548c05e2b57aa29c1ef15415b291a Mon Sep 17 00:00:00 2001 From: timklge <2026103+timklge@users.noreply.github.com> Date: Thu, 29 May 2025 19:56:54 +0200 Subject: [PATCH] Add profile selection dialog (#54) * Setup BASE_URL ci config * Add profile selection dialog * Update changelog * Enable pipeline for all branches * Fix BASE_URL * Add readme info * Update button styling * Only use profile selection dialog to input new profiles * Update button colors --- .github/workflows/android.yml | 9 +- README.md | 2 + app/build.gradle.kts | 2 +- .../de/timklge/karooreminder/Extensions.kt | 12 +++ .../karooreminder/KarooReminderExtension.kt | 66 +++++++----- .../karooreminder/screens/DetailScreen.kt | 101 +++++++++++++++++- .../karooreminder/screens/MainScreen.kt | 12 +-- .../timklge/karooreminder/screens/Reminder.kt | 13 ++- gradle/libs.versions.toml | 2 +- 9 files changed, 173 insertions(+), 46 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 11faee3..a5810ed 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -3,10 +3,10 @@ name: Build on: workflow_dispatch: push: - branches: [ "master" ] + branches: [ "**" ] tags: [ "*" ] pull_request: - branches: [ "master" ] + branches: [ "**" ] jobs: build: @@ -26,7 +26,7 @@ jobs: echo "KEYSTORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV echo "KEYSTORE_BASE64=${{ secrets.KEYSTORE_BASE64 }}" >> $GITHUB_ENV echo "BUILD_NUMBER=${{ github.run_number }}" >> $GITHUB_ENV - echo "BASE_URL=${{ secrets.BASE_URL || '"https://github.com/timklge/karoo-powerbar/releases/latest/download"' }}" >> $GITHUB_ENV + echo "BASE_URL=${{ secrets.BASE_URL || 'https://github.com/timklge/karoo-reminder/releases/latest/download' }}" >> $GITHUB_ENV - uses: actions/checkout@v4 - name: set up JDK 17 uses: actions/setup-java@v4 @@ -60,4 +60,5 @@ jobs: detail.png list.png env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/README.md b/README.md index f5d9833..047ceaf 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Karoo extension that displays in-ride alerts based on custom triggers. Reminders can be set to activate after a specific time interval, distance traveled, energy output or when a sensor value is outside a defined range (e.g., heart rate exceeds zone 2). +By default, created reminders are active for all ride profiles. If you want to limit reminders to specific ride profiles (e. g. your "Gravel" profile), you can do so in the reminder settings. + Compatible with Karoo 2 and Karoo 3 devices. ![Reminder List](list.png) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1a9d8e3..223273a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -73,7 +73,7 @@ tasks.register("generateManifest") { "latestVersionCode" to android.defaultConfig.versionCode, "developer" to "github.com/timklge", "description" to "Open-source extension that shows in-ride alerts after a given time interval has passed, distance has been traveled or HR / power / speed / cadence range is exceeded", - "releaseNotes" to "* Add rolling average setting for power triggers", + "releaseNotes" to "* Add profile selection dialog per reminder\n* Add rolling average setting for power triggers", "screenshotUrls" to listOf( "$baseUrl/reminder.png", "$baseUrl/list.png", diff --git a/app/src/main/kotlin/de/timklge/karooreminder/Extensions.kt b/app/src/main/kotlin/de/timklge/karooreminder/Extensions.kt index bbdd2b7..59246cc 100644 --- a/app/src/main/kotlin/de/timklge/karooreminder/Extensions.kt +++ b/app/src/main/kotlin/de/timklge/karooreminder/Extensions.kt @@ -7,6 +7,7 @@ import de.timklge.karooreminder.screens.Reminder import de.timklge.karooreminder.screens.defaultReminders import de.timklge.karooreminder.screens.preferencesKey import io.hammerhead.karooext.KarooSystemService +import io.hammerhead.karooext.models.ActiveRideProfile import io.hammerhead.karooext.models.OnStreamState import io.hammerhead.karooext.models.RideState import io.hammerhead.karooext.models.StreamState @@ -40,6 +41,17 @@ fun KarooSystemService.streamRideState(): Flow { } } +fun KarooSystemService.streamActiveRideProfile(): Flow { + return callbackFlow { + val listenerId = addConsumer { activeProfile: ActiveRideProfile -> + trySendBlocking(activeProfile) + } + awaitClose { + removeConsumer(listenerId) + } + } +} + fun KarooSystemService.streamUserProfile(): Flow { return callbackFlow { val listenerId = addConsumer { userProfile: UserProfile -> diff --git a/app/src/main/kotlin/de/timklge/karooreminder/KarooReminderExtension.kt b/app/src/main/kotlin/de/timklge/karooreminder/KarooReminderExtension.kt index 7371dbc..1371c32 100644 --- a/app/src/main/kotlin/de/timklge/karooreminder/KarooReminderExtension.kt +++ b/app/src/main/kotlin/de/timklge/karooreminder/KarooReminderExtension.kt @@ -5,8 +5,10 @@ import android.media.MediaPlayer import android.util.Log import de.timklge.karooreminder.screens.Reminder import de.timklge.karooreminder.screens.ReminderBeepPattern +import de.timklge.karooreminder.screens.reminderIsActive import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.extension.KarooExtension +import io.hammerhead.karooext.models.ActiveRideProfile import io.hammerhead.karooext.models.DataType import io.hammerhead.karooext.models.HardwareType import io.hammerhead.karooext.models.InRideAlert @@ -231,13 +233,19 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS val triggerJobs = mutableSetOf() + data class StreamData(val preferences: MutableList, val activeProfile: ActiveRideProfile) + + val streamDataFlow = combine(streamPreferences(), karooSystem.streamActiveRideProfile()) { reminders, activeProfile -> + StreamData(preferences = reminders, activeProfile = activeProfile) + } + triggerStreamJob = CoroutineScope(Dispatchers.IO).launch { - streamPreferences().collect { reminders -> + streamDataFlow.collect { (reminders, activeRideProfile) -> triggerJobs.forEach { it.cancel() } triggerJobs.clear() if (reminders.any { it.trigger == ReminderTrigger.DISTANCE }){ - val distanceJob = startIntervalJob(ReminderTrigger.DISTANCE) { + val distanceJob = startIntervalJob(reminders, activeRideProfile, ReminderTrigger.DISTANCE) { karooSystem.streamDataFlow(DataType.Type.DISTANCE) .mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue } .combine(karooSystem.streamUserProfile()) { distance, profile -> distance to profile } @@ -255,7 +263,7 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS } if (reminders.any { it.trigger == ReminderTrigger.ELAPSED_TIME }){ - val elapsedTimeJob = startIntervalJob(ReminderTrigger.ELAPSED_TIME) { + val elapsedTimeJob = startIntervalJob(reminders, activeRideProfile, ReminderTrigger.ELAPSED_TIME) { karooSystem.streamDataFlow(DataType.Type.ELAPSED_TIME) .mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue } .map { (it / 1000 / 60).toInt() } @@ -266,7 +274,7 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS } if (reminders.any { it.trigger == ReminderTrigger.ENERGY_OUTPUT }){ - val energyOutputJob = startIntervalJob(ReminderTrigger.ENERGY_OUTPUT) { + val energyOutputJob = startIntervalJob(reminders, activeRideProfile, ReminderTrigger.ENERGY_OUTPUT) { karooSystem.streamDataFlow(DataType.Type.ENERGY_OUTPUT) .mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue } .map { it.toInt() } @@ -301,7 +309,7 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS intervalTriggers.forEach { trigger -> SmoothSetting.entries.forEach { smoothSetting -> if (reminders.any { it.trigger == trigger && it.smoothSetting == smoothSetting }){ - val job = startRangeExceededJob(trigger, smoothSetting) + val job = startRangeExceededJob(reminders, activeRideProfile, trigger, smoothSetting) triggerJobs.add(job) } } @@ -310,41 +318,43 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS } } - private fun startIntervalJob(trigger: ReminderTrigger, flow: () -> Flow): Job { + private fun startIntervalJob(preferences: List, activeRideProfile: ActiveRideProfile, trigger: ReminderTrigger, flow: () -> Flow): Job { return CoroutineScope(Dispatchers.IO).launch { - val preferences = streamPreferences() flow() .filterNot { it == 0 } - .combine(preferences) { elapsedMinutes, reminders -> elapsedMinutes to reminders} - .distinctUntilChanged { old, new -> old.first == new.first } - .collectLatest { (elapsedMinutes, reminders) -> - val rs = reminders + .distinctUntilChanged() + .collectLatest { elapsedMinutes -> + val rs = preferences .filter { reminder -> val interval = reminder.interval - reminder.trigger == trigger && reminder.isActive && interval != null && elapsedMinutes % interval == 0 + reminder.trigger == trigger && reminderIsActive(reminder, activeRideProfile.profile) && interval != null && elapsedMinutes % interval == 0 } - for (reminder in rs){ + for (reminder in rs) { Log.i(TAG, "$trigger reminder: ${reminder.name}") - reminderChannel.send(DisplayedReminder(reminder.tone, trigger, InRideAlert( - id = "reminder-${reminder.id}-${elapsedMinutes}", - detail = reminder.text, - title = reminder.name, - autoDismissMs = if(reminder.isAutoDismiss) reminder.autoDismissSeconds * 1000L else null, - icon = R.drawable.timer, - textColor = reminder.displayForegroundColor?.getTextColor() ?: R.color.black, - backgroundColor = reminder.displayForegroundColor?.colorRes ?: R.color.hRed - ))) + reminderChannel.send( + DisplayedReminder( + reminder.tone, trigger, InRideAlert( + id = "reminder-${reminder.id}-${elapsedMinutes}", + detail = reminder.text, + title = reminder.name, + autoDismissMs = if (reminder.isAutoDismiss) reminder.autoDismissSeconds * 1000L else null, + icon = R.drawable.timer, + textColor = reminder.displayForegroundColor?.getTextColor() + ?: R.color.black, + backgroundColor = reminder.displayForegroundColor?.colorRes + ?: R.color.hRed + ) + ) + ) } } } } - private fun startRangeExceededJob(triggerType: ReminderTrigger, smoothSetting: SmoothSetting): Job { + private fun startRangeExceededJob(preferences: MutableList, activeRideProfile: ActiveRideProfile, triggerType: ReminderTrigger, smoothSetting: SmoothSetting): Job { return CoroutineScope(Dispatchers.IO).launch { - val preferences = streamPreferences() - Log.i(TAG, "Starting range exceeded job for trigger $triggerType with smooth setting $smoothSetting") val valueStream = karooSystem.streamDataFlow(triggerType.getSmoothedDataType(smoothSetting)) @@ -370,9 +380,9 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS data class StreamData(val value: Double, val reminders: MutableList, val distanceImperial: Boolean, val temperatureImperial: Boolean, val rideState: RideState) - combine(valueStream, preferences, karooSystem.streamUserProfile(), karooSystem.streamRideState()) { value, reminders, profile, rideState -> + combine(valueStream, karooSystem.streamUserProfile(), karooSystem.streamRideState()) { value, profile, rideState -> StreamData(distanceImperial = profile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL, temperatureImperial = profile.preferredUnit.temperature == UserProfile.PreferredUnit.UnitType.IMPERIAL, - value = value, reminders = reminders, rideState = rideState) + value = value, reminders = preferences, rideState = rideState) }.filter { it.rideState is RideState.Recording }.let { @@ -432,7 +442,7 @@ class KarooReminderExtension : KarooExtension("karoo-reminder", BuildConfig.VERS ReminderTrigger.ELAPSED_TIME, ReminderTrigger.DISTANCE, ReminderTrigger.ENERGY_OUTPUT -> error("Unsupported trigger type: $triggerType") } - reminder.isActive && reminder.trigger == triggerType && triggerIsMet + reminderIsActive(reminder, activeRideProfile.profile) && reminder.trigger == triggerType && triggerIsMet } triggered diff --git a/app/src/main/kotlin/de/timklge/karooreminder/screens/DetailScreen.kt b/app/src/main/kotlin/de/timklge/karooreminder/screens/DetailScreen.kt index efb2476..4e70d7d 100644 --- a/app/src/main/kotlin/de/timklge/karooreminder/screens/DetailScreen.kt +++ b/app/src/main/kotlin/de/timklge/karooreminder/screens/DetailScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Build import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Delete @@ -25,6 +26,7 @@ import androidx.compose.material.icons.filled.Done import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon @@ -103,6 +105,8 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi var selectedTone by remember { mutableStateOf(reminder.tone) } var autoDismissSeconds by remember { mutableStateOf(reminder.autoDismissSeconds.toString()) } var selectedTrigger by remember { mutableStateOf(reminder.trigger) } + var rideProfileDialogVisible by remember { mutableStateOf(false) } + var enabledRideProfiles by remember { mutableStateOf(reminder.enabledRideProfiles.toMutableSet()) } val profile by karooSystem.streamUserProfile().collectAsStateWithLifecycle(null) @@ -116,7 +120,8 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi isActive = isActive, smoothSetting = smoothSetting, trigger = selectedTrigger, - isAutoDismiss = autoDismiss, tone = selectedTone, autoDismissSeconds = autoDismissSeconds.toIntOrNull() ?: 15) + isAutoDismiss = autoDismiss, tone = selectedTone, autoDismissSeconds = autoDismissSeconds.toIntOrNull() ?: 15, + enabledRideProfiles = enabledRideProfiles.toSet()) } Column(modifier = Modifier @@ -259,6 +264,41 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi ) } + Column(modifier = Modifier.fillMaxWidth()) { + if (enabledRideProfiles.isEmpty()) { + Text("Enabled for all profiles") + } else { + Text("Enabled for profiles:") + + enabledRideProfiles.forEach { profileName -> + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(profileName) + FilledTonalButton(onClick = { + enabledRideProfiles = enabledRideProfiles.toMutableSet().apply { remove(profileName) } + }) { + Icon(Icons.Default.Delete, contentDescription = "Delete profile") + } + } + } + } + } + + FilledTonalButton(modifier = Modifier + .fillMaxWidth() + .height(60.dp), onClick = { + rideProfileDialogVisible = true + }) { + Icon(Icons.Default.Build, contentDescription = "Change Profiles", modifier = Modifier.size(20.dp)) + Spacer(modifier = Modifier.width(5.dp)) + Text("Limit to Profile") + } + Row(verticalAlignment = Alignment.CenterVertically) { Switch(checked = isActive, onCheckedChange = { isActive = it}) Spacer(modifier = Modifier.width(10.dp)) @@ -310,6 +350,59 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi title = { Text("Delete reminder") }, text = { Text("Really delete this reminder?") }) } + if (rideProfileDialogVisible) { + var newProfileName by remember { mutableStateOf("") } + Dialog(onDismissRequest = { rideProfileDialogVisible = false }) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp), + shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) + ) { + Column( + modifier = Modifier + .padding(16.dp) + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + + OutlinedTextField( + value = newProfileName, + onValueChange = { newProfileName = it }, + label = { Text("New profile name") }, + modifier = Modifier.fillMaxWidth(), + singleLine = true + ) + FilledTonalButton( + onClick = { + if (newProfileName.isNotBlank()) { + enabledRideProfiles = enabledRideProfiles.toMutableSet().apply { add(newProfileName) } + newProfileName = "" + rideProfileDialogVisible = false + } + }, + modifier = Modifier.fillMaxWidth().height(60.dp) + ) { + Icon(Icons.Default.Add, contentDescription = "Add Profile") + Spacer(modifier = Modifier.width(5.dp)) + Text("Add Profile") + } + + FilledTonalButton( + onClick = { rideProfileDialogVisible = false }, + modifier = Modifier.fillMaxWidth().height(60.dp) + ) { + Icon(Icons.Default.Close, contentDescription = "Cancel Editing") + Spacer(modifier = Modifier.width(5.dp)) + Text("Close") + } + } + } + } + } + if (triggerDialogVisible){ Dialog(onDismissRequest = { triggerDialogVisible = false }) { Card( @@ -317,6 +410,7 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi .fillMaxWidth() .padding(10.dp), shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) ) { Column(modifier = Modifier .padding(5.dp) @@ -361,6 +455,7 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi .fillMaxWidth() .padding(10.dp), shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) ) { Column(modifier = Modifier .padding(5.dp) @@ -396,6 +491,7 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi .fillMaxWidth() .padding(10.dp), shape = RoundedCornerShape(10.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface) ) { Column(modifier = Modifier .padding(5.dp) @@ -429,4 +525,5 @@ fun DetailScreen(isCreating: Boolean, reminder: Reminder, onSubmit: (updatedRemi } } } -} \ No newline at end of file +} + diff --git a/app/src/main/kotlin/de/timklge/karooreminder/screens/MainScreen.kt b/app/src/main/kotlin/de/timklge/karooreminder/screens/MainScreen.kt index 0b3490e..9d7dfc3 100644 --- a/app/src/main/kotlin/de/timklge/karooreminder/screens/MainScreen.kt +++ b/app/src/main/kotlin/de/timklge/karooreminder/screens/MainScreen.kt @@ -20,13 +20,8 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Add import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.FabPosition -import androidx.compose.material3.FloatingActionButton -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface @@ -63,6 +58,7 @@ import androidx.navigation.navArgument import de.timklge.karooreminder.KarooReminderExtension import de.timklge.karooreminder.R import de.timklge.karooreminder.dataStore +import de.timklge.karooreminder.streamActiveRideProfile import de.timklge.karooreminder.streamUserProfile import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.models.UserProfile @@ -72,7 +68,6 @@ import kotlinx.coroutines.launch import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json - val preferencesKey = stringPreferencesKey("reminders") suspend fun saveReminders(context: Context, reminders: MutableList) { @@ -165,6 +160,7 @@ fun MainScreen(reminders: MutableList, onNavigateToReminder: (r: Remin var showWarnings by remember { mutableStateOf(false) } val profile by karooSystem.streamUserProfile().collectAsStateWithLifecycle(null) + val currentRideProfile by karooSystem.streamActiveRideProfile().collectAsStateWithLifecycle(null) LaunchedEffect(Unit) { delay(1000L) @@ -197,7 +193,7 @@ fun MainScreen(reminders: MutableList, onNavigateToReminder: (r: Remin Card(Modifier .fillMaxWidth() .height(60.dp) - .alpha(if (reminder.isActive) 1f else 0.6f) + .alpha(if (reminderIsActive(reminder, currentRideProfile?.profile)) 1f else 0.6f) .clickable { onNavigateToReminder(reminder) } .padding(5.dp), shape = RoundedCornerShape(corner = CornerSize(10.dp)) ) { @@ -258,4 +254,4 @@ fun MainScreen(reminders: MutableList, onNavigateToReminder: (r: Remin } } ) -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/de/timklge/karooreminder/screens/Reminder.kt b/app/src/main/kotlin/de/timklge/karooreminder/screens/Reminder.kt index 53bc565..5e305f4 100644 --- a/app/src/main/kotlin/de/timklge/karooreminder/screens/Reminder.kt +++ b/app/src/main/kotlin/de/timklge/karooreminder/screens/Reminder.kt @@ -7,6 +7,7 @@ import de.timklge.karooreminder.R import de.timklge.karooreminder.ReminderTrigger import de.timklge.karooreminder.SmoothSetting import io.hammerhead.karooext.models.PlayBeepPattern +import io.hammerhead.karooext.models.RideProfile import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -141,6 +142,14 @@ class Reminder(val id: Int, var name: String, val isActive: Boolean = true, val isAutoDismiss: Boolean = true, val tone: ReminderBeepPattern = ReminderBeepPattern.THREE_TONES_UP, var trigger: ReminderTrigger = ReminderTrigger.ELAPSED_TIME, - val autoDismissSeconds: Int = 15) + val autoDismissSeconds: Int = 15, + val enabledRideProfiles: Set = emptySet()) -val defaultReminders = Json.encodeToString(listOf(Reminder(0, "Drink", 30, text = "Take a sip!"))) \ No newline at end of file +val defaultReminders = Json.encodeToString(listOf(Reminder(0, "Drink", 30, text = "Take a sip!"))) + +fun reminderIsActive(reminder: Reminder, currentRideProfile: RideProfile?): Boolean { + val enabledRideProfiles = reminder.enabledRideProfiles.map { it.lowercase().trim() } + val currentProfileName = currentRideProfile?.name?.lowercase()?.trim() + + return reminder.isActive && (currentRideProfile == null || enabledRideProfiles.isEmpty() || enabledRideProfiles.contains(currentProfileName)) +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dddecba..261486c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " [libraries] androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" } color = { module = "com.maxkeppeler.sheets-compose-dialogs:color", version.ref = "color" } -hammerhead-karoo-ext = { group = "io.hammerhead", name = "karoo-ext", version = "1.1.1" } +hammerhead-karoo-ext = { group = "io.hammerhead", name = "karoo-ext", version = "1.1.5" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidxCore" }