Optimize the month cell display in the year summary.
This commit is contained in:
parent
7d2508a4de
commit
470c9ce706
19 changed files with 914 additions and 907 deletions
|
|
@ -3,7 +3,7 @@ package com.pixelized.headache.ui.navigation.destination
|
|||
import androidx.navigation3.runtime.EntryProviderBuilder
|
||||
import androidx.navigation3.runtime.entry
|
||||
import com.pixelized.headache.ui.navigation.Navigator
|
||||
import com.pixelized.headache.ui.page.summary.month.MonthSummaryPage
|
||||
import com.pixelized.headache.ui.page.summary.monthly.MonthSummaryPage
|
||||
|
||||
data object MonthSummaryDestination
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.pixelized.headache.ui.navigation.destination
|
|||
import androidx.navigation3.runtime.EntryProviderBuilder
|
||||
import androidx.navigation3.runtime.entry
|
||||
import com.pixelized.headache.ui.navigation.Navigator
|
||||
import com.pixelized.headache.ui.page.summary.year.YearSummaryPage
|
||||
import com.pixelized.headache.ui.page.summary.yearly.YearSummaryPage
|
||||
|
||||
|
||||
data object YearSummaryDestination
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
package com.pixelized.headache.ui.page.summary.month
|
||||
package com.pixelized.headache.ui.page.summary.monthly
|
||||
|
||||
import android.icu.util.Calendar
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.pixelized.headache.repository.event.Event
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryBoxUio
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryCell
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryItemUio
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryPillItemUio
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryTitleUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryBoxUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryCell
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryItemUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryPillItemUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryTitleUio
|
||||
import com.pixelized.headache.utils.extention.event
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.month
|
||||
package com.pixelized.headache.ui.page.summary.monthly
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.fadeIn
|
||||
|
|
@ -45,14 +45,14 @@ import com.pixelized.headache.ui.navigation.LocalNavigator
|
|||
import com.pixelized.headache.ui.navigation.destination.navigateToEventPage
|
||||
import com.pixelized.headache.ui.page.event.edit.EventEditBottomSheet
|
||||
import com.pixelized.headache.ui.page.event.edit.EventEditBottomSheetViewModel
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryBox
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryBoxUio
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryCell
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryItem
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryItemUio
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryPillItemUio
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryTitle
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryTitleUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryBox
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryBoxUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryCell
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryItem
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryItemUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryPillItemUio
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryTitle
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryTitleUio
|
||||
import com.pixelized.headache.ui.theme.HeadacheTheme
|
||||
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette
|
||||
import java.util.Date
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.pixelized.headache.ui.page.summary.month
|
||||
package com.pixelized.headache.ui.page.summary.monthly
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.headache.repository.event.Event
|
||||
import com.pixelized.headache.repository.event.EventRepository
|
||||
import com.pixelized.headache.ui.page.summary.month.item.MonthSummaryCell
|
||||
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryCell
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.month.item
|
||||
package com.pixelized.headache.ui.page.summary.monthly.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.icu.text.SimpleDateFormat
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.month.item
|
||||
package com.pixelized.headache.ui.page.summary.monthly.item
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import java.util.Date
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.month.item
|
||||
package com.pixelized.headache.ui.page.summary.monthly.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.icu.text.SimpleDateFormat
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.month.item
|
||||
package com.pixelized.headache.ui.page.summary.monthly.item
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.month.item
|
||||
package com.pixelized.headache.ui.page.summary.monthly.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.icu.text.SimpleDateFormat
|
||||
|
|
@ -1,483 +0,0 @@
|
|||
package com.pixelized.headache.ui.page.summary.year
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.keepScreenOn
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalWindowInfo
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.pixelized.headache.R
|
||||
import com.pixelized.headache.ui.navigation.LocalNavigator
|
||||
import com.pixelized.headache.ui.navigation.destination.navigateToEventPage
|
||||
import com.pixelized.headache.ui.page.event.edit.EventEditBottomSheet
|
||||
import com.pixelized.headache.ui.page.event.edit.EventEditBottomSheetViewModel
|
||||
import com.pixelized.headache.ui.page.summary.year.item.YearSummaryDayUio
|
||||
import com.pixelized.headache.ui.page.summary.year.item.YearSummaryMonth
|
||||
import com.pixelized.headache.ui.page.summary.year.item.YearSummaryMonthUio
|
||||
import com.pixelized.headache.ui.theme.HeadacheTheme
|
||||
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette
|
||||
import com.pixelized.headache.utils.extention.calculate
|
||||
import java.util.Calendar
|
||||
|
||||
@Stable
|
||||
data class YearUio(
|
||||
val year: Int,
|
||||
val months: List<YearSummaryMonthUio>,
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun YearSummaryPage(
|
||||
viewModel: YearSummaryViewModel = hiltViewModel(),
|
||||
editViewModel: EventEditBottomSheetViewModel = hiltViewModel(),
|
||||
) {
|
||||
val navigation = LocalNavigator.current
|
||||
val uio = viewModel.events.collectAsStateWithLifecycle()
|
||||
|
||||
YearSummaryContent(
|
||||
modifier = Modifier
|
||||
.systemBarsPadding()
|
||||
.keepScreenOn()
|
||||
.fillMaxSize(),
|
||||
uio = uio,
|
||||
onBack = {
|
||||
navigation.popBackstack()
|
||||
},
|
||||
onMonth = {
|
||||
navigation.navigateToEventPage(date = it.date)
|
||||
},
|
||||
onAddEvent = {
|
||||
editViewModel.show()
|
||||
},
|
||||
)
|
||||
|
||||
EventEditBottomSheet(
|
||||
viewModel = editViewModel,
|
||||
onDismissRequest = { editViewModel.dismiss() },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberDaySize(
|
||||
column: Int = 3,
|
||||
space: Dp,
|
||||
paddingValues: PaddingValues,
|
||||
): Dp {
|
||||
val density = LocalDensity.current
|
||||
val windowInfo = LocalWindowInfo.current
|
||||
val screenWidth = remember(density, windowInfo) {
|
||||
with(density) {
|
||||
windowInfo.containerSize.width.toDp()
|
||||
}
|
||||
}
|
||||
val (start, _, end, _) = paddingValues.calculate()
|
||||
return (screenWidth - space * (column - 1) - start - end) / (7 * column)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun YearSummaryContent(
|
||||
modifier: Modifier = Modifier,
|
||||
paddingValues: PaddingValues = PaddingValues(
|
||||
start = 16.dp,
|
||||
top = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp + 16.dp + 56.dp,
|
||||
),
|
||||
space: Dp = 8.dp,
|
||||
daySize: Dp = rememberDaySize(
|
||||
column = 3,
|
||||
paddingValues = paddingValues,
|
||||
space = space,
|
||||
),
|
||||
uio: State<List<YearUio>>,
|
||||
onBack: () -> Unit,
|
||||
onMonth: (YearSummaryMonthUio) -> Unit,
|
||||
onAddEvent: () -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = onBack,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = stringResource(R.string.year_summary_title))
|
||||
},
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
shape = CircleShape,
|
||||
onClick = onAddEvent,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
content = { it ->
|
||||
LazyVerticalGrid(
|
||||
modifier = Modifier.padding(paddingValues = it),
|
||||
columns = GridCells.Adaptive(minSize = daySize * 7),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = space),
|
||||
contentPadding = paddingValues,
|
||||
) {
|
||||
uio.value.forEachIndexed { index, (year, months) ->
|
||||
item(
|
||||
span = { GridItemSpan(maxLineSpan) },
|
||||
contentType = { "Title" },
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
top = when (index) {
|
||||
0 -> 0.dp
|
||||
else -> 16.dp
|
||||
}
|
||||
),
|
||||
style = MaterialTheme.typography.displaySmall,
|
||||
text = "$year",
|
||||
)
|
||||
}
|
||||
items(
|
||||
items = months,
|
||||
key = { it.date.time },
|
||||
contentType = { "Month" },
|
||||
) {
|
||||
YearSummaryMonth(
|
||||
uio = it,
|
||||
daySize = daySize,
|
||||
onMonth = onMonth,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview()
|
||||
private fun YearSummaryPreview(
|
||||
@PreviewParameter(YearPreviewProvider::class) preview: List<YearUio>,
|
||||
) {
|
||||
HeadacheTheme {
|
||||
Surface {
|
||||
YearSummaryContent(
|
||||
uio = remember { mutableStateOf(preview) },
|
||||
onBack = { },
|
||||
onMonth = { },
|
||||
onAddEvent = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class YearPreviewProvider() : PreviewParameterProvider<List<YearUio>> {
|
||||
|
||||
private var day = 1
|
||||
|
||||
private fun day(): () -> YearSummaryDayUio = {
|
||||
YearSummaryDayUio(
|
||||
number = day++,
|
||||
headache = false,
|
||||
pills = emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun headache(
|
||||
spifen: Boolean = false,
|
||||
eletriptan: Boolean = false,
|
||||
): () -> YearSummaryDayUio = {
|
||||
YearSummaryDayUio(
|
||||
number = day++,
|
||||
headache = true,
|
||||
pills = listOfNotNull(
|
||||
if (spifen) HeadacheColorPalette.Pill.Spifen400 else null,
|
||||
if (eletriptan) HeadacheColorPalette.Pill.Eletriptan40 else null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// inline to avoid un sequential call to "day()" between default and overridden function parameters.
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private fun week(
|
||||
mon: (() -> YearSummaryDayUio)? = day(),
|
||||
tue: (() -> YearSummaryDayUio)? = day(),
|
||||
wen: (() -> YearSummaryDayUio)? = day(),
|
||||
thu: (() -> YearSummaryDayUio)? = day(),
|
||||
fry: (() -> YearSummaryDayUio)? = day(),
|
||||
sat: (() -> YearSummaryDayUio)? = day(),
|
||||
sun: (() -> YearSummaryDayUio)? = day(),
|
||||
): List<YearSummaryDayUio> = listOfNotNull(
|
||||
mon?.invoke(),
|
||||
tue?.invoke(),
|
||||
wen?.invoke(),
|
||||
thu?.invoke(),
|
||||
fry?.invoke(),
|
||||
sat?.invoke(),
|
||||
sun?.invoke(),
|
||||
)
|
||||
|
||||
private fun month(
|
||||
month: Int,
|
||||
year: Int,
|
||||
vararg weeks: List<YearSummaryDayUio>,
|
||||
): YearSummaryMonthUio {
|
||||
day = 1
|
||||
return YearSummaryMonthUio(
|
||||
date = Calendar.getInstance().apply {
|
||||
set(Calendar.YEAR, year)
|
||||
set(Calendar.MONTH, month)
|
||||
}.time,
|
||||
weeks = weeks.toList(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun year(
|
||||
year: Int,
|
||||
vararg months: YearSummaryMonthUio,
|
||||
) = YearUio(
|
||||
year = year,
|
||||
months = months.toList(),
|
||||
)
|
||||
|
||||
override val values: Sequence<List<YearUio>> = sequenceOf(
|
||||
listOf(
|
||||
year(
|
||||
year = 2025,
|
||||
month(
|
||||
month = Calendar.JANUARY,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.FEBRUARY,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MARCH,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(tue = null, wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.APRIL,
|
||||
year = 2025,
|
||||
week(mon = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MAY,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.JUNE,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null, sat = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(tue = null, wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.JULY,
|
||||
year = 2025,
|
||||
week(mon = null, sun = headache(spifen = true)),
|
||||
week(wen = headache(spifen = true)),
|
||||
week(sat = headache()),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
thu = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
week(wen = headache(), fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.AUGUST,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null),
|
||||
week(wen = headache(), fry = headache()),
|
||||
week(fry = headache(spifen = true)),
|
||||
week(tue = headache(spifen = true), fry = headache()),
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = Calendar.SEPTEMBER,
|
||||
year = 2025,
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(spifen = true),
|
||||
fry = headache(),
|
||||
sat = headache(),
|
||||
sun = headache(),
|
||||
),
|
||||
week(
|
||||
sun = headache(spifen = true),
|
||||
),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
tue = headache(),
|
||||
),
|
||||
week(),
|
||||
week(wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.OCTOBER,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.NOVEMBER,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
),
|
||||
month(
|
||||
month = Calendar.DECEMBER,
|
||||
year = 2025,
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
),
|
||||
year(
|
||||
year = 2024,
|
||||
month(
|
||||
month = Calendar.JANUARY,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.FEBRUARY,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MARCH,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(tue = null, wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.APRIL,
|
||||
year = 2024,
|
||||
week(mon = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MAY,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.JUNE,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null, sat = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(tue = null, wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
package com.pixelized.headache.ui.page.summary.year.item
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.headache.ui.theme.HeadacheTheme
|
||||
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette
|
||||
|
||||
@Stable
|
||||
object YearSummaryDayDefault {
|
||||
@Stable
|
||||
val size: Dp = 16.dp
|
||||
|
||||
@Stable
|
||||
val pill: Dp = 2.dp
|
||||
}
|
||||
|
||||
@Stable
|
||||
data class YearSummaryDayUio(
|
||||
val number: Int,
|
||||
val headache: Boolean,
|
||||
val pills: List<Color>,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun YearSummaryDay(
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp = YearSummaryDayDefault.size,
|
||||
pill: Dp = YearSummaryDayDefault.pill,
|
||||
day: YearSummaryDayUio,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(size = size)
|
||||
.then(other = modifier),
|
||||
) {
|
||||
if (day.headache) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.padding(vertical = pill + 1.dp)
|
||||
.background(color = HeadacheColorPalette.Pill.Unknown)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
modifier = Modifier.align(alignment = Alignment.Center),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = when {
|
||||
!isSystemInDarkTheme() && day.headache -> Color.White
|
||||
else -> MaterialTheme.colorScheme.onSurface
|
||||
},
|
||||
text = "${day.number}",
|
||||
)
|
||||
|
||||
if (day.headache) {
|
||||
Row(
|
||||
modifier = Modifier.align(alignment = Alignment.BottomCenter),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 1.dp),
|
||||
) {
|
||||
day.pills.forEach {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(color = it)
|
||||
.size(size = pill)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
private fun YearSummaryDayPreview(
|
||||
@PreviewParameter(DayPreviewProvider::class) preview: YearSummaryDayUio,
|
||||
) {
|
||||
HeadacheTheme {
|
||||
Surface {
|
||||
YearSummaryDay(
|
||||
modifier = Modifier.size(size = 16.dp),
|
||||
day = preview,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DayPreviewProvider() : PreviewParameterProvider<YearSummaryDayUio> {
|
||||
override val values: Sequence<YearSummaryDayUio>
|
||||
get() = sequenceOf(
|
||||
YearSummaryDayUio(
|
||||
number = 1,
|
||||
headache = false,
|
||||
pills = emptyList(),
|
||||
),
|
||||
YearSummaryDayUio(
|
||||
number = 2,
|
||||
headache = true,
|
||||
pills = emptyList(),
|
||||
),
|
||||
YearSummaryDayUio(
|
||||
number = 3,
|
||||
headache = true,
|
||||
pills = listOf(
|
||||
HeadacheColorPalette.Pill.Eletriptan40,
|
||||
),
|
||||
),
|
||||
YearSummaryDayUio(
|
||||
number = 3,
|
||||
headache = true,
|
||||
pills = listOf(
|
||||
HeadacheColorPalette.Pill.Eletriptan40,
|
||||
HeadacheColorPalette.Pill.Ibuprofene400,
|
||||
HeadacheColorPalette.Pill.Spifen400,
|
||||
HeadacheColorPalette.Pill.Paracetamol1000,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
package com.pixelized.headache.ui.page.summary.year.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.icu.text.DateFormat
|
||||
import android.icu.text.SimpleDateFormat
|
||||
import android.icu.util.Calendar
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ripple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.headache.ui.theme.HeadacheTheme
|
||||
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette
|
||||
import com.pixelized.headache.utils.extention.capitalize
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@Stable
|
||||
data object YearSummaryMonthDefault {
|
||||
@SuppressLint("ConstantLocale")
|
||||
@Stable
|
||||
val formatter = SimpleDateFormat("MMMM", Locale.getDefault())
|
||||
}
|
||||
|
||||
@Stable
|
||||
data class YearSummaryMonthUio(
|
||||
val date: Date,
|
||||
val weeks: List<List<YearSummaryDayUio>>,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun YearSummaryMonth(
|
||||
modifier: Modifier = Modifier,
|
||||
formatter: DateFormat = YearSummaryMonthDefault.formatter,
|
||||
daySize: Dp,
|
||||
uio: YearSummaryMonthUio,
|
||||
onMonth: (YearSummaryMonthUio) -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = ripple(bounded = false),
|
||||
onClick = { onMonth(uio) }
|
||||
)
|
||||
.then(other = modifier),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.align(alignment = Alignment.Start),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
text = remember(uio.date) { formatter.format(uio.date) }.capitalize(),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier.size(width = daySize * 7, height = daySize * 6),
|
||||
) {
|
||||
uio.weeks.forEachIndexed { row, week ->
|
||||
week.forEachIndexed { column, day ->
|
||||
YearSummaryDay(
|
||||
Modifier.offset(
|
||||
x = when (row) {
|
||||
0 -> daySize * (column + 7 - week.size)
|
||||
else -> daySize * column
|
||||
},
|
||||
y = daySize * row,
|
||||
),
|
||||
size = daySize,
|
||||
day = day,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
private fun YearSummaryMonthPreview(
|
||||
@PreviewParameter(MonthPreviewProvider::class) preview: YearSummaryMonthUio,
|
||||
) {
|
||||
HeadacheTheme {
|
||||
Surface {
|
||||
YearSummaryMonth(
|
||||
modifier = Modifier.padding(all = 8.dp),
|
||||
daySize = YearSummaryDayDefault.size,
|
||||
uio = preview,
|
||||
onMonth = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MonthPreviewProvider() : PreviewParameterProvider<YearSummaryMonthUio> {
|
||||
|
||||
private var day: Int = 1
|
||||
|
||||
private fun day(): () -> YearSummaryDayUio = {
|
||||
YearSummaryDayUio(
|
||||
number = day++,
|
||||
headache = false,
|
||||
pills = emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun headache(
|
||||
spifen: Boolean = false,
|
||||
eletriptan: Boolean = false,
|
||||
): () -> YearSummaryDayUio = {
|
||||
YearSummaryDayUio(
|
||||
number = day++,
|
||||
headache = true,
|
||||
pills = listOfNotNull(
|
||||
if (spifen) HeadacheColorPalette.Pill.Spifen400 else null,
|
||||
if (eletriptan) HeadacheColorPalette.Pill.Eletriptan40 else null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// inline to avoid un sequential call to "day()" between default and overridden function parameters.
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private fun week(
|
||||
mon: (() -> YearSummaryDayUio)? = day(),
|
||||
tue: (() -> YearSummaryDayUio)? = day(),
|
||||
wen: (() -> YearSummaryDayUio)? = day(),
|
||||
thu: (() -> YearSummaryDayUio)? = day(),
|
||||
fry: (() -> YearSummaryDayUio)? = day(),
|
||||
sat: (() -> YearSummaryDayUio)? = day(),
|
||||
sun: (() -> YearSummaryDayUio)? = day(),
|
||||
): List<YearSummaryDayUio> = listOfNotNull(
|
||||
mon?.invoke(),
|
||||
tue?.invoke(),
|
||||
wen?.invoke(),
|
||||
thu?.invoke(),
|
||||
fry?.invoke(),
|
||||
sat?.invoke(),
|
||||
sun?.invoke(),
|
||||
)
|
||||
|
||||
private fun month(
|
||||
month: Int,
|
||||
vararg weeks: List<YearSummaryDayUio>,
|
||||
): YearSummaryMonthUio {
|
||||
day = 1
|
||||
return YearSummaryMonthUio(
|
||||
date = java.util.Calendar.getInstance().apply {
|
||||
set(java.util.Calendar.YEAR, 2025)
|
||||
set(java.util.Calendar.MONTH, month)
|
||||
}.time,
|
||||
weeks = weeks.toList(),
|
||||
)
|
||||
}
|
||||
|
||||
override val values: Sequence<YearSummaryMonthUio>
|
||||
get() = sequenceOf(
|
||||
month(
|
||||
month = Calendar.MARCH,
|
||||
week(
|
||||
mon = null,
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = headache(spifen = true)
|
||||
),
|
||||
week(sat = headache(spifen = true)),
|
||||
week(
|
||||
wen = headache(spifen = true, eletriptan = true),
|
||||
thu = headache(spifen = true, eletriptan = true),
|
||||
fry = headache(spifen = true, eletriptan = true),
|
||||
sat = headache(),
|
||||
sun = headache(spifen = true, eletriptan = true)
|
||||
),
|
||||
week(
|
||||
mon = headache(),
|
||||
tue = headache(),
|
||||
sat = headache(spifen = true, eletriptan = true),
|
||||
),
|
||||
week(thu = headache(), fry = headache(), sat = headache()),
|
||||
week(
|
||||
mon = headache(spifen = true, eletriptan = true),
|
||||
tue = null, wen = null, thu = null, fry = null, sat = null, sun = null
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = java.util.Calendar.JULY,
|
||||
week(mon = null, sun = headache(spifen = true)),
|
||||
week(wen = headache(spifen = true)),
|
||||
week(sat = headache()),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
thu = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
week(wen = headache(), fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = java.util.Calendar.AUGUST,
|
||||
week(mon = null, tue = null, wen = null, thu = null),
|
||||
week(wen = headache(), fry = headache()),
|
||||
week(fry = headache(spifen = true)),
|
||||
week(tue = headache(spifen = true), fry = headache()),
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = java.util.Calendar.SEPTEMBER,
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(spifen = true),
|
||||
fry = headache(),
|
||||
sat = headache(),
|
||||
sun = headache(),
|
||||
),
|
||||
week(
|
||||
sun = headache(spifen = true),
|
||||
),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
tue = headache(),
|
||||
),
|
||||
week(),
|
||||
week(wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
package com.pixelized.headache.ui.page.summary.year
|
||||
package com.pixelized.headache.ui.page.summary.yearly
|
||||
|
||||
import android.icu.util.Calendar
|
||||
import com.pixelized.headache.repository.event.Event
|
||||
import com.pixelized.headache.ui.page.summary.year.item.YearSummaryDayUio
|
||||
import com.pixelized.headache.ui.page.summary.year.item.YearSummaryMonthUio
|
||||
import com.pixelized.headache.ui.page.summary.yearly.YearSummaryMonthUio.DayUio
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class YearSummaryFactory @Inject constructor() {
|
||||
|
||||
fun convertToUio(
|
||||
|
|
@ -70,7 +68,7 @@ class YearSummaryFactory @Inject constructor() {
|
|||
val initial = MutableList(
|
||||
size = monthLastDayCalendar.get(Calendar.WEEK_OF_MONTH),
|
||||
) {
|
||||
mutableListOf<YearSummaryDayUio>()
|
||||
mutableListOf<DayUio>()
|
||||
}
|
||||
val weeks = (1..monthLastDayCalendar.get(Calendar.DAY_OF_MONTH))
|
||||
.fold(initial = initial) { accumulator, dayNumber ->
|
||||
|
|
@ -83,7 +81,7 @@ class YearSummaryFactory @Inject constructor() {
|
|||
set(Calendar.MILLISECONDS_IN_DAY, 1)
|
||||
}
|
||||
.get(Calendar.WEEK_OF_MONTH) - 1
|
||||
val day = YearSummaryDayUio(
|
||||
val day = DayUio(
|
||||
number = dayNumber,
|
||||
headache = event != null,
|
||||
pills = event?.pills?.map { it.color } ?: emptyList(),
|
||||
|
|
@ -0,0 +1,346 @@
|
|||
package com.pixelized.headache.ui.page.summary.yearly
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.icu.text.DateFormat
|
||||
import android.icu.text.SimpleDateFormat
|
||||
import android.icu.util.Calendar
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ripple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.TextMeasurer
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.drawText
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.headache.ui.theme.HeadacheTheme
|
||||
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette
|
||||
import com.pixelized.headache.utils.extention.capitalize
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@Stable
|
||||
data object YearSummaryMonthDefault {
|
||||
|
||||
@Stable
|
||||
val daySize: Dp = 16.dp
|
||||
|
||||
@Stable
|
||||
val pillSize: Dp = 2.dp
|
||||
|
||||
@Stable
|
||||
val pillSpace: Dp = 1.dp
|
||||
|
||||
@SuppressLint("ConstantLocale")
|
||||
@Stable
|
||||
val formatter = SimpleDateFormat("MMMM", Locale.getDefault())
|
||||
}
|
||||
|
||||
@Stable
|
||||
data class YearSummaryMonthUio(
|
||||
val date: Date,
|
||||
val weeks: List<List<DayUio>>,
|
||||
) {
|
||||
@Stable
|
||||
data class DayUio(
|
||||
val number: Int,
|
||||
val headache: Boolean,
|
||||
val pills: List<Color>,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun YearSummaryMonth(
|
||||
modifier: Modifier = Modifier,
|
||||
formatter: DateFormat = YearSummaryMonthDefault.formatter,
|
||||
defaultTextStyle: TextStyle,
|
||||
headacheTextStyle: TextStyle,
|
||||
daySize: Dp = YearSummaryMonthDefault.daySize,
|
||||
pillSize: Dp = YearSummaryMonthDefault.pillSize,
|
||||
pillSpace: Dp = YearSummaryMonthDefault.pillSpace,
|
||||
uio: YearSummaryMonthUio,
|
||||
onMonth: (YearSummaryMonthUio) -> Unit,
|
||||
) {
|
||||
val textMeasurer: TextMeasurer = rememberTextMeasurer()
|
||||
val pill: Float = with(LocalDensity.current) { pillSize.toPx() }
|
||||
val space: Float = with(LocalDensity.current) { pillSpace.toPx() }
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = ripple(bounded = false),
|
||||
onClick = { onMonth(uio) }
|
||||
)
|
||||
.then(other = modifier),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.align(alignment = Alignment.Start),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
text = remember(uio.date) { formatter.format(uio.date) }.capitalize(),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(width = daySize * 7, height = daySize * 6)
|
||||
.drawWithCache {
|
||||
val cellSize = Size(
|
||||
width = size.width / 7f,
|
||||
height = size.height / 6f,
|
||||
)
|
||||
val pillSize = Size(
|
||||
width = pill,
|
||||
height = pill,
|
||||
)
|
||||
|
||||
onDrawBehind {
|
||||
var localCellOffset: Offset = Offset.Zero
|
||||
var localCellSize: Size = Size.Zero
|
||||
|
||||
uio.weeks.forEachIndexed { row, week ->
|
||||
week.forEachIndexed { column, day ->
|
||||
// Compute current cell offset and size
|
||||
localCellOffset = Offset(
|
||||
x = when (row) {
|
||||
0 -> cellSize.width * (column + 7 - week.size)
|
||||
else -> cellSize.width * column
|
||||
},
|
||||
y = cellSize.height * row,
|
||||
)
|
||||
localCellSize = Size(
|
||||
width = cellSize.width,
|
||||
height = cellSize.height,
|
||||
)
|
||||
|
||||
// draw background
|
||||
if (day.headache) {
|
||||
drawRect(
|
||||
topLeft = Offset(
|
||||
x = localCellOffset.x - 1f,
|
||||
y = localCellOffset.y + pillSize.height + space,
|
||||
),
|
||||
size = Size(
|
||||
width = localCellSize.width - 0f,
|
||||
height = localCellSize.height - (pillSize.height + space) * 2,
|
||||
),
|
||||
color = HeadacheColorPalette.Pill.Unknown,
|
||||
)
|
||||
}
|
||||
|
||||
// draw day number
|
||||
val label = "${day.number}"
|
||||
val measure = textMeasurer.measure(label, defaultTextStyle)
|
||||
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = label,
|
||||
style = when {
|
||||
day.headache -> headacheTextStyle
|
||||
else -> defaultTextStyle
|
||||
},
|
||||
topLeft = Offset(
|
||||
x = localCellOffset.x + (localCellSize.width - measure.size.width) / 2,
|
||||
y = localCellOffset.y + (localCellSize.height - measure.size.height) / 2,
|
||||
),
|
||||
)
|
||||
|
||||
// draw pills
|
||||
day.pills.forEachIndexed { index, pill ->
|
||||
drawRect(
|
||||
topLeft = Offset(
|
||||
x = localCellOffset.x + (localCellSize.width - (pillSize.width + space) * day.pills.size) / 2f + index * (pillSize.width + space),
|
||||
y = localCellOffset.y + localCellSize.height - pillSize.height,
|
||||
),
|
||||
size = pillSize,
|
||||
color = pill
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
private fun YearSummaryMonthPreview(
|
||||
@PreviewParameter(MonthPreviewProvider::class) preview: YearSummaryMonthUio,
|
||||
) {
|
||||
HeadacheTheme {
|
||||
Surface {
|
||||
YearSummaryMonth(
|
||||
modifier = Modifier.padding(all = 8.dp),
|
||||
defaultTextStyle = MaterialTheme.typography.labelSmall,
|
||||
headacheTextStyle = MaterialTheme.typography.labelSmall.copy(color = Color.White),
|
||||
uio = preview,
|
||||
onMonth = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object MonthPreviewProviderHelper {
|
||||
private var day: Int = 1
|
||||
|
||||
fun day(): () -> YearSummaryMonthUio.DayUio = {
|
||||
YearSummaryMonthUio.DayUio(
|
||||
number = day++,
|
||||
headache = false,
|
||||
pills = emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
fun headache(
|
||||
spifen: Boolean = false,
|
||||
eletriptan: Boolean = false,
|
||||
): () -> YearSummaryMonthUio.DayUio = {
|
||||
YearSummaryMonthUio.DayUio(
|
||||
number = day++,
|
||||
headache = true,
|
||||
pills = listOfNotNull(
|
||||
if (spifen) HeadacheColorPalette.Pill.Spifen400 else null,
|
||||
if (eletriptan) HeadacheColorPalette.Pill.Eletriptan40 else null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// inline to avoid un sequential call to "day()" between default and overridden function parameters.
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
fun week(
|
||||
mon: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
tue: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
wen: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
thu: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
fry: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
sat: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
sun: (() -> YearSummaryMonthUio.DayUio)? = day(),
|
||||
): List<YearSummaryMonthUio.DayUio> = listOfNotNull(
|
||||
mon?.invoke(),
|
||||
tue?.invoke(),
|
||||
wen?.invoke(),
|
||||
thu?.invoke(),
|
||||
fry?.invoke(),
|
||||
sat?.invoke(),
|
||||
sun?.invoke(),
|
||||
)
|
||||
|
||||
fun month(
|
||||
month: Int,
|
||||
year: Int,
|
||||
vararg weeks: List<YearSummaryMonthUio.DayUio>,
|
||||
): YearSummaryMonthUio {
|
||||
day = 1
|
||||
return YearSummaryMonthUio(
|
||||
date = java.util.Calendar.getInstance().apply {
|
||||
set(java.util.Calendar.YEAR, year)
|
||||
set(java.util.Calendar.MONTH, month)
|
||||
}.time,
|
||||
weeks = weeks.toList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class MonthPreviewProvider() : PreviewParameterProvider<YearSummaryMonthUio> {
|
||||
override val values: Sequence<YearSummaryMonthUio>
|
||||
get() = with(MonthPreviewProviderHelper) {
|
||||
sequenceOf(
|
||||
month(
|
||||
month = Calendar.MARCH,
|
||||
year = 2025,
|
||||
week(
|
||||
mon = null,
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = headache(spifen = true)
|
||||
),
|
||||
week(sat = headache(spifen = true)),
|
||||
week(
|
||||
wen = headache(spifen = true, eletriptan = true),
|
||||
thu = headache(spifen = true, eletriptan = true),
|
||||
fry = headache(spifen = true, eletriptan = true),
|
||||
sat = headache(),
|
||||
sun = headache(spifen = true, eletriptan = true)
|
||||
),
|
||||
week(
|
||||
mon = headache(),
|
||||
tue = headache(),
|
||||
sat = headache(spifen = true, eletriptan = true),
|
||||
),
|
||||
week(thu = headache(), fry = headache(), sat = headache()),
|
||||
week(
|
||||
mon = headache(spifen = true, eletriptan = true),
|
||||
tue = null, wen = null, thu = null, fry = null, sat = null, sun = null
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = java.util.Calendar.JULY,
|
||||
year = 2025,
|
||||
week(mon = null, sun = headache(spifen = true)),
|
||||
week(wen = headache(spifen = true)),
|
||||
week(sat = headache()),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
thu = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
week(wen = headache(), fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = java.util.Calendar.AUGUST,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null),
|
||||
week(wen = headache(), fry = headache()),
|
||||
week(fry = headache(spifen = true)),
|
||||
week(tue = headache(spifen = true), fry = headache()),
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = java.util.Calendar.SEPTEMBER,
|
||||
year = 2025,
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(spifen = true),
|
||||
fry = headache(),
|
||||
sat = headache(),
|
||||
sun = headache(),
|
||||
),
|
||||
week(
|
||||
sun = headache(spifen = true),
|
||||
),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
tue = headache(),
|
||||
),
|
||||
week(),
|
||||
week(wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,477 @@
|
|||
package com.pixelized.headache.ui.page.summary.yearly
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.keepScreenOn
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalWindowInfo
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.pixelized.headache.R
|
||||
import com.pixelized.headache.ui.navigation.LocalNavigator
|
||||
import com.pixelized.headache.ui.navigation.destination.navigateToEventPage
|
||||
import com.pixelized.headache.ui.page.event.edit.EventEditBottomSheet
|
||||
import com.pixelized.headache.ui.page.event.edit.EventEditBottomSheetViewModel
|
||||
import com.pixelized.headache.ui.theme.HeadacheTheme
|
||||
import com.pixelized.headache.ui.theme.headache
|
||||
import com.pixelized.headache.utils.extention.calculate
|
||||
import java.util.Calendar
|
||||
|
||||
@Stable
|
||||
data class YearUio(
|
||||
val year: Int,
|
||||
val months: List<YearSummaryMonthUio>,
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun YearSummaryPage(
|
||||
viewModel: YearSummaryViewModel = hiltViewModel(),
|
||||
editViewModel: EventEditBottomSheetViewModel = hiltViewModel(),
|
||||
) {
|
||||
val navigation = LocalNavigator.current
|
||||
val uio = viewModel.events.collectAsStateWithLifecycle()
|
||||
|
||||
YearSummaryContent(
|
||||
modifier = Modifier
|
||||
.systemBarsPadding()
|
||||
.keepScreenOn()
|
||||
.fillMaxSize(),
|
||||
uio = uio,
|
||||
onBack = {
|
||||
navigation.popBackstack()
|
||||
},
|
||||
onMonth = {
|
||||
navigation.navigateToEventPage(date = it.date)
|
||||
},
|
||||
onAddEvent = {
|
||||
editViewModel.show()
|
||||
},
|
||||
)
|
||||
|
||||
EventEditBottomSheet(
|
||||
viewModel = editViewModel,
|
||||
onDismissRequest = { editViewModel.dismiss() },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberDaySize(
|
||||
column: Int,
|
||||
space: Dp,
|
||||
paddingValues: PaddingValues,
|
||||
): Dp {
|
||||
val density = LocalDensity.current
|
||||
val windowInfo = LocalWindowInfo.current
|
||||
val screenWidth = remember(density, windowInfo) {
|
||||
with(density) { windowInfo.containerSize.width.toDp() }
|
||||
}
|
||||
val (start, _, end, _) = paddingValues.calculate()
|
||||
return remember {
|
||||
(screenWidth - space * (column - 1) - start - end) / (7 * column)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun YearSummaryContent(
|
||||
modifier: Modifier = Modifier,
|
||||
paddingValues: PaddingValues = PaddingValues(
|
||||
start = 16.dp,
|
||||
top = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp + 16.dp + 56.dp,
|
||||
),
|
||||
space: Dp = 8.dp,
|
||||
daySize: Dp = rememberDaySize(
|
||||
column = 3,
|
||||
paddingValues = paddingValues,
|
||||
space = space,
|
||||
),
|
||||
uio: State<List<YearUio>>,
|
||||
onBack: () -> Unit,
|
||||
onMonth: (YearSummaryMonthUio) -> Unit,
|
||||
onAddEvent: () -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = onBack,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = stringResource(R.string.year_summary_title))
|
||||
},
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
shape = CircleShape,
|
||||
onClick = onAddEvent,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
content = { it ->
|
||||
val typography = MaterialTheme.typography
|
||||
val colorScheme = MaterialTheme.headache.colorScheme
|
||||
val defaultTextStyle = remember(typography, colorScheme) {
|
||||
typography.labelSmall.copy(color = colorScheme.base.onSurface)
|
||||
}
|
||||
val headacheTextStyle = remember(typography, colorScheme) {
|
||||
defaultTextStyle.copy(color = colorScheme.calendar.onHeadache)
|
||||
}
|
||||
LazyVerticalGrid(
|
||||
modifier = Modifier.padding(paddingValues = it),
|
||||
columns = GridCells.Adaptive(minSize = daySize * 7),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = space),
|
||||
verticalArrangement = Arrangement.spacedBy(space = space),
|
||||
contentPadding = paddingValues,
|
||||
) {
|
||||
uio.value.forEachIndexed { index, (year, months) ->
|
||||
item(
|
||||
span = { GridItemSpan(maxLineSpan) },
|
||||
contentType = { "Title" },
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
top = when (index) {
|
||||
0 -> 0.dp
|
||||
else -> 16.dp
|
||||
}
|
||||
),
|
||||
style = MaterialTheme.typography.displaySmall,
|
||||
text = "$year",
|
||||
)
|
||||
}
|
||||
items(
|
||||
items = months,
|
||||
key = { it.date.time },
|
||||
contentType = { "Month" },
|
||||
) {
|
||||
YearSummaryMonth(
|
||||
uio = it,
|
||||
defaultTextStyle = defaultTextStyle,
|
||||
headacheTextStyle = headacheTextStyle,
|
||||
daySize = daySize,
|
||||
onMonth = onMonth,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview()
|
||||
private fun YearSummaryPreview(
|
||||
@PreviewParameter(YearPreviewProvider::class) preview: List<YearUio>,
|
||||
) {
|
||||
HeadacheTheme {
|
||||
Surface {
|
||||
YearSummaryContent(
|
||||
uio = remember { mutableStateOf(preview) },
|
||||
onBack = { },
|
||||
onMonth = { },
|
||||
onAddEvent = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class YearPreviewProvider() : PreviewParameterProvider<List<YearUio>> {
|
||||
|
||||
private fun year(
|
||||
year: Int,
|
||||
vararg months: YearSummaryMonthUio,
|
||||
) = YearUio(
|
||||
year = year,
|
||||
months = months.toList(),
|
||||
)
|
||||
|
||||
override val values: Sequence<List<YearUio>>
|
||||
get() = with(MonthPreviewProviderHelper) {
|
||||
sequenceOf(
|
||||
listOf(
|
||||
year(
|
||||
year = 2025,
|
||||
month(
|
||||
month = Calendar.JANUARY,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.FEBRUARY,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MARCH,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = null,
|
||||
sun = null
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = Calendar.APRIL,
|
||||
year = 2025,
|
||||
week(mon = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MAY,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.JUNE,
|
||||
year = 2025,
|
||||
week(
|
||||
mon = null,
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = null
|
||||
),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = null,
|
||||
sun = null
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = Calendar.JULY,
|
||||
year = 2025,
|
||||
week(mon = null, sun = headache(spifen = true)),
|
||||
week(wen = headache(spifen = true)),
|
||||
week(sat = headache()),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
thu = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
week(wen = headache(), fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.AUGUST,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null),
|
||||
week(wen = headache(), fry = headache()),
|
||||
week(fry = headache(spifen = true)),
|
||||
week(tue = headache(spifen = true), fry = headache()),
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(),
|
||||
sat = headache(spifen = true),
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = Calendar.SEPTEMBER,
|
||||
year = 2025,
|
||||
week(
|
||||
tue = headache(spifen = true, eletriptan = true),
|
||||
wen = headache(spifen = true),
|
||||
fry = headache(),
|
||||
sat = headache(),
|
||||
sun = headache(),
|
||||
),
|
||||
week(
|
||||
sun = headache(spifen = true),
|
||||
),
|
||||
week(
|
||||
wen = headache(spifen = true),
|
||||
tue = headache(),
|
||||
),
|
||||
week(),
|
||||
week(wen = null, thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.OCTOBER,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.NOVEMBER,
|
||||
year = 2025,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
),
|
||||
month(
|
||||
month = Calendar.DECEMBER,
|
||||
year = 2025,
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
),
|
||||
year(
|
||||
year = 2024,
|
||||
month(
|
||||
month = Calendar.JANUARY,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.FEBRUARY,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MARCH,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null, thu = null, fry = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = null,
|
||||
sun = null
|
||||
),
|
||||
),
|
||||
month(
|
||||
month = Calendar.APRIL,
|
||||
year = 2024,
|
||||
week(mon = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(thu = null, fry = null, sat = null, sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.MAY,
|
||||
year = 2024,
|
||||
week(mon = null, tue = null, wen = null),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(sun = null),
|
||||
),
|
||||
month(
|
||||
month = Calendar.JUNE,
|
||||
year = 2024,
|
||||
week(
|
||||
mon = null,
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = null
|
||||
),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(),
|
||||
week(
|
||||
tue = null,
|
||||
wen = null,
|
||||
thu = null,
|
||||
fry = null,
|
||||
sat = null,
|
||||
sun = null
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.headache.ui.page.summary.year
|
||||
package com.pixelized.headache.ui.page.summary.yearly
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
|
@ -3,6 +3,7 @@ package com.pixelized.headache.ui.theme
|
|||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
|
|
@ -10,15 +11,15 @@ import com.pixelized.headache.ui.theme.color.HeadacheColors
|
|||
import com.pixelized.headache.ui.theme.color.headacheDarkColorScheme
|
||||
import com.pixelized.headache.ui.theme.color.headacheLightColorScheme
|
||||
|
||||
val LocalLwaTheme = compositionLocalOf<HeadacheTheme> {
|
||||
error("Local Snack Controller is not yet ready")
|
||||
val LocalHeadacheTheme = compositionLocalOf<HeadacheTheme> {
|
||||
error("Local Theme Controller is not yet ready")
|
||||
}
|
||||
|
||||
val MaterialTheme.headache: HeadacheTheme
|
||||
@Stable
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalLwaTheme.current
|
||||
get() = LocalHeadacheTheme.current
|
||||
|
||||
@Stable
|
||||
data class HeadacheTheme(
|
||||
|
|
@ -30,14 +31,19 @@ fun HeadacheTheme(
|
|||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val colorScheme = when {
|
||||
darkTheme -> headacheDarkColorScheme()
|
||||
else -> headacheLightColorScheme()
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme.base,
|
||||
typography = Typography,
|
||||
content = content
|
||||
val theme = HeadacheTheme(
|
||||
colorScheme = when {
|
||||
darkTheme -> headacheDarkColorScheme()
|
||||
else -> headacheLightColorScheme()
|
||||
}
|
||||
)
|
||||
CompositionLocalProvider(
|
||||
LocalHeadacheTheme provides theme,
|
||||
) {
|
||||
MaterialTheme(
|
||||
colorScheme = theme.colorScheme.base,
|
||||
typography = Typography,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,25 +16,67 @@ import kotlin.math.ln
|
|||
@Stable
|
||||
data class HeadacheColors(
|
||||
val base: ColorScheme,
|
||||
)
|
||||
val calendar: Calendar,
|
||||
val pill: Pill,
|
||||
) {
|
||||
@Stable
|
||||
data class Calendar(
|
||||
val headache: Color,
|
||||
val onHeadache: Color,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class Pill(
|
||||
val unknown: Color,
|
||||
val ibuprofene400: Color,
|
||||
val paracetamol1000: Color,
|
||||
val spifen400: Color,
|
||||
val eletriptan40: Color,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
fun headacheDarkColorScheme(
|
||||
base: ColorScheme = darkColorScheme(),
|
||||
calendar: HeadacheColors.Calendar = HeadacheColors.Calendar(
|
||||
headache = HeadacheColorPalette.Additional.Red,
|
||||
onHeadache = Color.White,
|
||||
),
|
||||
pill: HeadacheColors.Pill = HeadacheColors.Pill(
|
||||
unknown = HeadacheColorPalette.Pill.Unknown,
|
||||
ibuprofene400 = HeadacheColorPalette.Pill.Ibuprofene400,
|
||||
paracetamol1000 = HeadacheColorPalette.Pill.Paracetamol1000,
|
||||
spifen400 = HeadacheColorPalette.Pill.Spifen400,
|
||||
eletriptan40 = HeadacheColorPalette.Pill.Eletriptan40,
|
||||
),
|
||||
) = HeadacheColors(
|
||||
base = base,
|
||||
calendar = calendar,
|
||||
pill = pill,
|
||||
)
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
fun headacheLightColorScheme(
|
||||
base: ColorScheme = lightColorScheme(),
|
||||
calendar: HeadacheColors.Calendar = HeadacheColors.Calendar(
|
||||
headache = HeadacheColorPalette.Additional.Red,
|
||||
onHeadache = Color.White,
|
||||
),
|
||||
pill: HeadacheColors.Pill = HeadacheColors.Pill(
|
||||
unknown = HeadacheColorPalette.Pill.Unknown,
|
||||
ibuprofene400 = HeadacheColorPalette.Pill.Ibuprofene400,
|
||||
paracetamol1000 = HeadacheColorPalette.Pill.Paracetamol1000,
|
||||
spifen400 = HeadacheColorPalette.Pill.Spifen400,
|
||||
eletriptan40 = HeadacheColorPalette.Pill.Eletriptan40,
|
||||
),
|
||||
) = HeadacheColors(
|
||||
base = base,
|
||||
calendar = calendar,
|
||||
pill = pill,
|
||||
)
|
||||
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
fun calculateElevatedColor(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue