diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 69e8615..fdf8d99 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 773fe0f..8978d23 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/app/build.gradle b/app/build.gradle
index ba814af..16c0807 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,14 +19,14 @@ spotless {
android {
namespace 'seamuslowry.daytracker'
- compileSdk 33
+ compileSdk 34
defaultConfig {
applicationId "seamuslowry.daytracker"
minSdk 33
- targetSdk 33
- versionCode 17
- versionName "0.23.1"
+ targetSdk 34
+ versionCode 18
+ versionName "0.23.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@@ -100,7 +100,7 @@ dependencies {
debugImplementation "androidx.compose.ui:ui-test-manifest"
}
-task printVersionName {
+tasks.register('printVersionName') {
doLast {
println android.defaultConfig.versionName
}
diff --git a/app/src/main/java/seamuslowry/daytracker/data/repos/SettingsRepo.kt b/app/src/main/java/seamuslowry/daytracker/data/repos/SettingsRepo.kt
index 4078b7d..220878e 100644
--- a/app/src/main/java/seamuslowry/daytracker/data/repos/SettingsRepo.kt
+++ b/app/src/main/java/seamuslowry/daytracker/data/repos/SettingsRepo.kt
@@ -5,6 +5,7 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import dagger.hilt.android.qualifiers.ApplicationContext
@@ -22,6 +23,7 @@ class SettingsRepo @Inject constructor(@ApplicationContext private val context:
val REMINDER_ENABLED = booleanPreferencesKey("REMINDER_ENABLED_KEY")
val REMINDER_TIME = stringPreferencesKey("REMINDER_TIME")
val SHOW_RECORDED_VALUES = booleanPreferencesKey("SHOW_RECORDED_VALUES")
+ val MIN_CALENDAR_SIZE = floatPreferencesKey("MIN_CALENDAR_SIZE")
}
suspend fun setReminderEnabled(enabled: Boolean) {
@@ -42,12 +44,19 @@ class SettingsRepo @Inject constructor(@ApplicationContext private val context:
}
}
+ suspend fun setMinCalendarSize(minSize: Float) {
+ context.dataStore.edit {
+ it[MIN_CALENDAR_SIZE] = minSize
+ }
+ }
+
val settings: Flow = context.dataStore.data
.map {
Settings(
reminderEnabled = it[REMINDER_ENABLED] ?: false,
reminderTime = it[REMINDER_TIME]?.let { time -> LocalTime.parse(time) } ?: LocalTime.of(18, 0),
showRecordedValues = it[SHOW_RECORDED_VALUES] ?: false,
+ minCalendarSize = it[MIN_CALENDAR_SIZE],
)
}
}
@@ -56,4 +65,5 @@ data class Settings(
val reminderEnabled: Boolean = false,
val reminderTime: LocalTime = LocalTime.of(18, 0),
val showRecordedValues: Boolean = false,
+ val minCalendarSize: Float? = null,
)
diff --git a/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportScreen.kt b/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportScreen.kt
index af99fe5..4591fdc 100644
--- a/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportScreen.kt
+++ b/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportScreen.kt
@@ -1,51 +1,27 @@
package seamuslowry.daytracker.ui.screens.report
-import android.animation.ArgbEvaluator
-import androidx.compose.animation.animateContentSize
-import androidx.compose.animation.core.tween
-import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.aspectRatio
-import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.grid.GridCells
-import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
-import androidx.compose.foundation.lazy.grid.items
-import androidx.compose.material3.Card
-import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
-import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
-import androidx.core.graphics.ColorUtils
import androidx.hilt.navigation.compose.hiltViewModel
import seamuslowry.daytracker.R
-import seamuslowry.daytracker.models.ItemConfiguration
import seamuslowry.daytracker.models.localeFormat
import seamuslowry.daytracker.ui.shared.ArrowPicker
+import seamuslowry.daytracker.ui.shared.CalendarGrid
import java.time.LocalDate
-import java.time.format.TextStyle
-import java.util.Locale
@Composable
fun ReportScreen(
@@ -81,16 +57,12 @@ fun ReportScreen(
onSelect = viewModel::select,
modifier = Modifier.fillMaxWidth(),
)
- LazyVerticalGrid(
- columns = GridCells.Adaptive(minSize = 192.dp),
- horizontalArrangement = Arrangement.spacedBy(16.dp),
- verticalArrangement = Arrangement.spacedBy(16.dp),
- contentPadding = PaddingValues(16.dp),
- ) {
- items(items = groupedItems.entries.toList(), key = { it.key.id }) {
- DisplayDates(entry = it, onSelectDate = onSelectDate)
- }
- }
+ CalendarGrid(
+ groupedItems = groupedItems,
+ onSelectDate = onSelectDate,
+ minCalendarSize = 288.dp,
+ spacing = 16.dp,
+ )
}
}
@@ -107,130 +79,3 @@ fun DisplaySelection(
}
}
}
-
-@Composable
-fun DisplayDates(
- entry: Map.Entry>>,
- modifier: Modifier = Modifier,
- onSelectDate: (d: LocalDate) -> Unit = {},
-) {
- Card(modifier = modifier) {
- Column(
- modifier = Modifier
- .animateContentSize(animationSpec = tween(300))
- .fillMaxWidth()
- .padding(8.dp),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center,
- ) {
- Text(text = entry.key.name, style = MaterialTheme.typography.titleLarge)
- Divider(modifier = Modifier.padding(4.dp), color = MaterialTheme.colorScheme.onSurfaceVariant)
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .padding(vertical = 8.dp),
- horizontalArrangement = Arrangement.Center,
- ) {
- entry.value.first().forEach {
- Text(
- text = it.date.dayOfWeek.getDisplayName(
- TextStyle.SHORT,
- Locale.getDefault(),
- ),
- textAlign = TextAlign.Center,
- modifier = Modifier.weight(1f),
- style = MaterialTheme.typography.bodySmall,
- )
- }
- }
-
- entry.value.forEach {
- Row(modifier = Modifier.fillMaxWidth().aspectRatio(7f), horizontalArrangement = Arrangement.Center) {
- it.forEach {
- DisplayDate(
- date = it,
- modifier = Modifier.weight(1f),
- onSelectDate = { onSelectDate(it.date) },
- )
- }
- }
- }
- }
- }
-}
-
-@Composable
-fun DisplayDate(
- date: DateDisplay,
- modifier: Modifier = Modifier,
- onSelectDate: () -> Unit = {},
-) {
- val color = when {
- !date.inRange -> Color.Transparent
- date.value == null || date.maxValue == null -> Color.Transparent
- else -> Color(ArgbEvaluator().evaluate(date.value.toFloat().div(date.maxValue), MaterialTheme.colorScheme.error.toArgb(), MaterialTheme.colorScheme.primary.toArgb()) as Int)
- }
-
- val textAlpha = when {
- !date.inRange -> 0.5f
- else -> 1f
- }
-
- val textColor = when {
- color == Color.Transparent -> MaterialTheme.colorScheme.onBackground
- ColorUtils.calculateContrast(MaterialTheme.colorScheme.onPrimary.toArgb(), color.toArgb()) > 2.5f -> MaterialTheme.colorScheme.onPrimary
- ColorUtils.calculateContrast(MaterialTheme.colorScheme.onError.toArgb(), color.toArgb()) > 2.5f -> MaterialTheme.colorScheme.onError
- else -> MaterialTheme.colorScheme.onBackground
- }
-
- val value = when {
- date.text != null -> stringResource(date.text)
- date.value != null -> date.value.toString()
- else -> null
- }
-
- val smallText = when {
- date.showValue -> date.date.dayOfMonth.toString()
- else -> null
- }
-
- val largeText = when {
- date.showValue -> value
- else -> date.date.dayOfMonth.toString()
- }
-
- Box(
- contentAlignment = Alignment.Center,
- modifier = modifier
- .background(color)
- .fillMaxHeight()
- .clickable(
- enabled = date.date <= LocalDate.now(),
- onClick = onSelectDate,
- ),
- ) {
- if (smallText != null) {
- Text(
- text = smallText,
- color = textColor,
- modifier = Modifier
- .align(Alignment.TopStart)
- .alpha(textAlpha)
- .padding(horizontal = 4.dp),
- textAlign = TextAlign.Center,
- style = MaterialTheme.typography.bodySmall,
- fontWeight = FontWeight.ExtraLight,
- )
- }
- if (largeText != null) {
- Text(
- text = largeText,
- color = textColor,
- modifier = Modifier.alpha(textAlpha),
- textAlign = TextAlign.Center,
- style = MaterialTheme.typography.bodyMedium,
- fontWeight = FontWeight.Light,
- )
- }
- }
-}
diff --git a/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportViewModel.kt b/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportViewModel.kt
index 10aed7e..0b10694 100644
--- a/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportViewModel.kt
+++ b/app/src/main/java/seamuslowry/daytracker/ui/screens/report/ReportViewModel.kt
@@ -18,6 +18,8 @@ import seamuslowry.daytracker.data.repos.ItemRepo
import seamuslowry.daytracker.data.repos.SettingsRepo
import seamuslowry.daytracker.models.Item
import seamuslowry.daytracker.models.ItemConfiguration
+import seamuslowry.daytracker.ui.shared.DateDisplay
+import seamuslowry.daytracker.ui.shared.mapToCalendarStructure
import java.time.LocalDate
import java.time.temporal.ChronoField
import java.time.temporal.ChronoUnit
@@ -63,27 +65,7 @@ class ReportViewModel @Inject constructor(
val displayItems: StateFlow