From 9e5d28bc5c5673af18bc3c88bab5350d1582e039 Mon Sep 17 00:00:00 2001 From: Jumpeee Date: Wed, 27 Sep 2023 23:20:30 +0200 Subject: [PATCH] Displaying number of expirations and warnings --- app/build.gradle.kts | 4 +- app/src/main/AndroidManifest.xml | 13 +++- .../main/java/io/fixmyride/MainActivity.kt | 2 +- .../io/fixmyride/enums/NotificationType.kt | 13 +++- .../java/io/fixmyride/models/Notification.kt | 4 +- .../notifications/NotificationItem.kt | 73 ++++++++++++++----- .../main/java/io/fixmyride/ui/theme/Typing.kt | 9 +++ .../io/fixmyride/ui/widgets/Expirations.kt | 37 ++++++++++ .../java/io/fixmyride/utils/DataExchange.kt | 34 --------- .../io/fixmyride/utils/NotificationChecker.kt | 31 +++++--- app/src/main/res/values-pl/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/expirations_widget.xml | 9 +++ 13 files changed, 160 insertions(+), 73 deletions(-) create mode 100644 app/src/main/java/io/fixmyride/ui/widgets/Expirations.kt create mode 100644 app/src/main/res/xml/expirations_widget.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bd6c9d7..a586676 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -64,8 +64,10 @@ dependencies { implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") - implementation("androidx.navigation:navigation-compose:2.7.2") + implementation("androidx.navigation:navigation-compose:2.7.3") implementation("com.google.code.gson:gson:2.10.1") + implementation("androidx.glance:glance-appwidget:1.0.0") + implementation("androidx.glance:glance-material3:1.0.0") testImplementation("junit:junit:4.13.2") androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 71ef7bd..5e85d2b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,13 +15,24 @@ + + + + + + + diff --git a/app/src/main/java/io/fixmyride/MainActivity.kt b/app/src/main/java/io/fixmyride/MainActivity.kt index 51a2fe3..b794a05 100644 --- a/app/src/main/java/io/fixmyride/MainActivity.kt +++ b/app/src/main/java/io/fixmyride/MainActivity.kt @@ -34,7 +34,7 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) DatabaseManager.initialize(this) PrefsManager.initialize(this) - + val prefs = PrefsManager.getInstance() if (prefs.getInt("notifications_days", -1) == -1) { prefs.edit().putInt("notifications_days", 7).apply() diff --git a/app/src/main/java/io/fixmyride/enums/NotificationType.kt b/app/src/main/java/io/fixmyride/enums/NotificationType.kt index 3a06585..64ac74f 100644 --- a/app/src/main/java/io/fixmyride/enums/NotificationType.kt +++ b/app/src/main/java/io/fixmyride/enums/NotificationType.kt @@ -1,7 +1,12 @@ package io.fixmyride.enums -enum class NotificationType { - TPL_EXPIRY, - CI_EXPIRY, - UPCOMING_INSPECTION; +object NotificationType { + const val TPL_ABOUT_TO_EXPIRE = 1 + const val TPL_EXPIRED = -1 + + const val CI_ABOUT_TO_EXPIRE = 2 + const val CI_EXPIRED = -2 + + const val INSPECTION_UPCOMING = 3 + const val INSPECTION_EXPIRED = -3 } \ No newline at end of file diff --git a/app/src/main/java/io/fixmyride/models/Notification.kt b/app/src/main/java/io/fixmyride/models/Notification.kt index c9649ef..79e7b72 100644 --- a/app/src/main/java/io/fixmyride/models/Notification.kt +++ b/app/src/main/java/io/fixmyride/models/Notification.kt @@ -1,8 +1,6 @@ package io.fixmyride.models -import io.fixmyride.enums.NotificationType - data class Notification( val relatedVehicleId: Int, - val expirations: List, + val expirations: List, ) \ No newline at end of file diff --git a/app/src/main/java/io/fixmyride/ui/components/notifications/NotificationItem.kt b/app/src/main/java/io/fixmyride/ui/components/notifications/NotificationItem.kt index 83cbdef..c710cb3 100644 --- a/app/src/main/java/io/fixmyride/ui/components/notifications/NotificationItem.kt +++ b/app/src/main/java/io/fixmyride/ui/components/notifications/NotificationItem.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.fixmyride.R @@ -94,7 +95,11 @@ fun NotificationItem(notification: Notification) { } } - WarningsAndExpand(notification.expirations.size, isExpanded.value) { + WarningsAndExpand( + expired = notification.expirations.filter { it < 0 }.size, + warnings = notification.expirations.filter { it > 0 }.size, + expanded = isExpanded.value, + ) { isExpanded.value = !isExpanded.value } } @@ -103,29 +108,63 @@ fun NotificationItem(notification: Notification) { @Composable fun WarningsAndExpand( + expired: Int, warnings: Int, expanded: Boolean, onClickExpand: () -> Unit, ) { + val hasOnlyExpirationsOrWarnings = when { + expired == 0 && warnings != 0 -> true + expired != 0 && warnings == 0 -> true + else -> false + } + Row { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .background( - color = ColorPalette.yellow.copy(alpha = 0.1f), - shape = RoundedCornerShape(5.dp), + if (expired != 0) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .background( + color = ColorPalette.lightRed.copy(alpha = 0.1f), + shape = RoundedCornerShape(5.dp), + ) + .clip(RoundedCornerShape(5.dp)) + ) { + Text( + text = "$expired ${if (hasOnlyExpirationsOrWarnings) stringResource(R.string.expirations) else ""}".trim(), + style = Typing.expiredText, + modifier = Modifier + .padding( + horizontal = 5.dp, + vertical = 2.dp, + ), ) - .clip(RoundedCornerShape(5.dp)) - ) { - Text( - text = "$warnings warnings", - style = Typing.warningText, + } + } + + if (!hasOnlyExpirationsOrWarnings) Spacer(Modifier.width(5.dp)) + + + if (warnings != 0) { + Box( + contentAlignment = Alignment.Center, modifier = Modifier - .padding( - horizontal = 5.dp, - vertical = 2.dp, - ), - ) + .background( + color = ColorPalette.yellow.copy(alpha = 0.1f), + shape = RoundedCornerShape(5.dp), + ) + .clip(RoundedCornerShape(5.dp)) + ) { + Text( + text = "$warnings ${if (hasOnlyExpirationsOrWarnings) stringResource(R.string.warnings) else ""}".trim(), + style = Typing.warningText, + modifier = Modifier + .padding( + horizontal = 5.dp, + vertical = 2.dp, + ), + ) + } } Spacer(Modifier.width(10.dp)) diff --git a/app/src/main/java/io/fixmyride/ui/theme/Typing.kt b/app/src/main/java/io/fixmyride/ui/theme/Typing.kt index 2cb3ba4..4cc17ea 100644 --- a/app/src/main/java/io/fixmyride/ui/theme/Typing.kt +++ b/app/src/main/java/io/fixmyride/ui/theme/Typing.kt @@ -132,6 +132,15 @@ object Typing { lineHeight = 16.sp, ) + /** e.g. notifications for every single vehicle expiration text */ + val expiredText = TextStyle( + color = ColorPalette.lightRed, + fontFamily = customFont, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + ) + /** Used only for text field texts */ val textFieldText = TextStyle( color = ColorPalette.secondary, diff --git a/app/src/main/java/io/fixmyride/ui/widgets/Expirations.kt b/app/src/main/java/io/fixmyride/ui/widgets/Expirations.kt new file mode 100644 index 0000000..09f54c5 --- /dev/null +++ b/app/src/main/java/io/fixmyride/ui/widgets/Expirations.kt @@ -0,0 +1,37 @@ +package io.fixmyride.ui.widgets + +import android.content.Context +import androidx.glance.GlanceId +import androidx.glance.GlanceModifier +import androidx.glance.appwidget.GlanceAppWidget +import androidx.glance.appwidget.GlanceAppWidgetReceiver +import androidx.glance.appwidget.provideContent +import androidx.glance.background +import androidx.glance.layout.Column +import androidx.glance.layout.fillMaxSize +import androidx.glance.text.Text +import io.fixmyride.ui.theme.ColorPalette + +private object ExpirationsWidget : GlanceAppWidget() { + override suspend fun provideGlance(context: Context, id: GlanceId) { + + // In this method, load data needed to render the AppWidget. + // Use `withContext` to switch to another thread for long running + // operations. + provideContent { + Column( + modifier = GlanceModifier + .fillMaxSize() + .background(color = ColorPalette.background), + ) { + Text("Sup'") + } + } + } + +} + +object ExpirationsReceiver : GlanceAppWidgetReceiver() { + override val glanceAppWidget: GlanceAppWidget + get() = ExpirationsWidget +} diff --git a/app/src/main/java/io/fixmyride/utils/DataExchange.kt b/app/src/main/java/io/fixmyride/utils/DataExchange.kt index 88c7bb6..6b107e0 100644 --- a/app/src/main/java/io/fixmyride/utils/DataExchange.kt +++ b/app/src/main/java/io/fixmyride/utils/DataExchange.kt @@ -1,17 +1,5 @@ package io.fixmyride.utils -import android.os.Build -import android.os.Environment -import androidx.annotation.RequiresApi -import com.google.gson.Gson -import io.fixmyride.database.DatabaseManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.io.File -import java.io.FileOutputStream -import java.io.IOException -import java.time.LocalDate - /** Provides functions for importing and exporting data to/from files */ object DataExchange { /** Used for importing data from previously exported file */ @@ -20,29 +8,7 @@ object DataExchange { } /** Used for exporting data to a file */ - @RequiresApi(Build.VERSION_CODES.O) suspend fun exportData() { - val vehicleData = DatabaseManager.getInstance().dao.getData() - val gson = Gson() - val fileName = "FixMyRide_${LocalDate.now()}.json" - val file = File("${Environment.getExternalStorageDirectory()}/${File.separator}$fileName") - - try { - val dataToConvert = mutableListOf>() - for (v in vehicleData) dataToConvert.add(v.toMap()) - val json = gson.toJson(dataToConvert) - - withContext(Dispatchers.IO) { - if (!file.exists()) { - file.createNewFile() - } - val fos = FileOutputStream(file) - fos.write(json.toByteArray()) - fos.close() - } - } catch (e: IOException) { - e.printStackTrace() - } } } \ No newline at end of file diff --git a/app/src/main/java/io/fixmyride/utils/NotificationChecker.kt b/app/src/main/java/io/fixmyride/utils/NotificationChecker.kt index 6ee7a13..6f36e04 100644 --- a/app/src/main/java/io/fixmyride/utils/NotificationChecker.kt +++ b/app/src/main/java/io/fixmyride/utils/NotificationChecker.kt @@ -10,28 +10,35 @@ import java.time.LocalDate /** Provides methods used for checking if vehicle's insurance (or inspection) is about to expire */ object NotificationChecker { @RequiresApi(Build.VERSION_CODES.O) - fun checkForNotifications(v: Vehicle): List { - val expired = arrayListOf() - val notifDays = PrefsManager.getInstance().getInt("notifications_days", -1) + fun checkForNotifications(v: Vehicle): List { + val expired = arrayListOf() + val notificationDays = PrefsManager.getInstance().getInt("notifications_days", -1) + + fun dateDifference(date: LocalDate): Long = + date.minusDays(LocalDate.now().toEpochDay()).toEpochDay() - fun dateDifference(date: LocalDate): Long { - return date.minusDays(LocalDate.now().toEpochDay()).toEpochDay() - } - if (dateDifference(v.tplInsuranceExpiry) in 1..notifDays) { - expired.add(NotificationType.TPL_EXPIRY) + val tplDifference = dateDifference(v.tplInsuranceExpiry) + when { + tplDifference < 0 -> expired.add(NotificationType.TPL_EXPIRED) + tplDifference in 1..notificationDays -> expired.add(NotificationType.TPL_ABOUT_TO_EXPIRE) } if (v.collisionInsuranceExpiry != null) { - if (dateDifference(v.collisionInsuranceExpiry) in 1..notifDays) { - expired.add(NotificationType.CI_EXPIRY) + val ciDifference = dateDifference(v.collisionInsuranceExpiry) + when { + ciDifference < 0 -> expired.add(NotificationType.CI_EXPIRED) + ciDifference in 1..notificationDays -> expired.add(NotificationType.CI_ABOUT_TO_EXPIRE) } } - if (dateDifference(v.nextInspectionDate) in 1..notifDays) { - expired.add(NotificationType.UPCOMING_INSPECTION) + val inspectionDifference = dateDifference(v.nextInspectionDate) + when { + inspectionDifference < 0 -> expired.add(NotificationType.INSPECTION_EXPIRED) + inspectionDifference in 1..notificationDays -> expired.add(NotificationType.INSPECTION_UPCOMING) } + return expired } } \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 6fff17b..180e4cc 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -58,4 +58,6 @@ Według daty przeglądu Ilość dni dni + wygaśnięcia + ostrzeżenia \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0fa8676..1c9ea40 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,4 +58,6 @@ By inspection date Number of days days + expirations + warnings \ No newline at end of file diff --git a/app/src/main/res/xml/expirations_widget.xml b/app/src/main/res/xml/expirations_widget.xml new file mode 100644 index 0000000..ba5e76c --- /dev/null +++ b/app/src/main/res/xml/expirations_widget.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file