feat: add marked divider
This commit is contained in:
parent
d7a2a26097
commit
5e15a75664
@ -2,6 +2,7 @@ package ru.sweetbread.unn.ui.composes
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -10,6 +11,7 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
@ -23,6 +25,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@ -31,15 +34,19 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import com.kizitonwose.calendar.compose.WeekCalendar
|
||||
import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.sweetbread.unn.Auditorium
|
||||
import ru.sweetbread.unn.Building
|
||||
@ -56,7 +63,9 @@ import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Calendar
|
||||
|
||||
@Composable
|
||||
fun Schedule() {
|
||||
@ -132,8 +141,37 @@ fun ScheduleDay(modifier: Modifier = Modifier, date: LocalDate) {
|
||||
|
||||
@Composable
|
||||
fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit, expanded: Boolean = false) {
|
||||
fun getRel(begin: Long, end: Long, now: Long): Float {
|
||||
if ((begin > now) or (now > end))
|
||||
return -1f
|
||||
return (now - begin) / (end - begin).toFloat()
|
||||
}
|
||||
|
||||
val begin = unit.begin.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
val end = unit.end.format(DateTimeFormatter.ofPattern("HH:mm"))
|
||||
var rel by remember {
|
||||
mutableFloatStateOf(getRel(
|
||||
LocalDateTime.of(unit.date, unit.begin).atZone(ZoneId.of("Europe/Moscow")).toEpochSecond(),
|
||||
LocalDateTime.of(unit.date, unit.end).atZone(ZoneId.of("Europe/Moscow")).toEpochSecond(),
|
||||
LocalDateTime.now().atZone(ZoneId.of("Europe/Moscow")).toEpochSecond()
|
||||
))
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
while (true) {
|
||||
val now = System.currentTimeMillis()
|
||||
val calendar = Calendar.getInstance().apply { timeInMillis = now }
|
||||
val seconds = calendar.get(Calendar.SECOND)
|
||||
val millisUntilNextMinute = (60 - seconds) * 1000L - calendar.get(Calendar.MILLISECOND)
|
||||
|
||||
delay(millisUntilNextMinute)
|
||||
rel = getRel(
|
||||
LocalDateTime.of(unit.date, unit.begin).atZone(ZoneId.of("Europe/Moscow")).toEpochSecond(),
|
||||
LocalDateTime.of(unit.date, unit.end).atZone(ZoneId.of("Europe/Moscow")).toEpochSecond(),
|
||||
LocalDateTime.now().atZone(ZoneId.of("Europe/Moscow")).toEpochSecond()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row (
|
||||
modifier
|
||||
@ -141,16 +179,9 @@ fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit, expanded: Bo
|
||||
.padding(4.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(
|
||||
if ((LocalDateTime.of(
|
||||
unit.date,
|
||||
unit.begin
|
||||
) < LocalDateTime.now()) and (LocalDateTime.now() < LocalDateTime.of(
|
||||
unit.date,
|
||||
unit.end
|
||||
))
|
||||
)
|
||||
if (rel != -1f)
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
else MaterialTheme.colorScheme.secondaryContainer
|
||||
else MaterialTheme.colorScheme.surfaceContainer
|
||||
)
|
||||
.padding(8.dp)
|
||||
){
|
||||
@ -240,8 +271,18 @@ fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit, expanded: Bo
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
Row (Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
Row (Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(begin.toString(), fontWeight = FontWeight.Bold)
|
||||
if (rel != -1f)
|
||||
DividerWithMarker(
|
||||
Modifier.weight(1f).padding(horizontal = 2.dp),
|
||||
positionPercentage = rel,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
thickness = 3.dp,
|
||||
markerSize = 8.dp,
|
||||
markerColor = MaterialTheme.colorScheme.primary)
|
||||
Text(end.toString())
|
||||
}
|
||||
}
|
||||
@ -257,6 +298,43 @@ fun ScheduleItem(modifier: Modifier = Modifier, unit: ScheduleUnit, expanded: Bo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun DividerWithMarker(
|
||||
modifier: Modifier = Modifier,
|
||||
positionPercentage: Float, // от 0f до 1f (например, 0.5f = 50%)
|
||||
color: Color = Color.Gray,
|
||||
thickness: Dp = 1.dp,
|
||||
markerSize: Dp = 8.dp,
|
||||
markerColor: Color = Color.Red
|
||||
) {
|
||||
Canvas(modifier = modifier.height(thickness)) {
|
||||
val dividerHeight = thickness.toPx()
|
||||
val width = size.width
|
||||
val markerX = width * positionPercentage
|
||||
|
||||
drawLine(
|
||||
color = markerColor,
|
||||
start = Offset(0f, dividerHeight / 2),
|
||||
end = Offset(markerX, dividerHeight / 2),
|
||||
strokeWidth = dividerHeight
|
||||
)
|
||||
|
||||
drawLine(
|
||||
color = color,
|
||||
start = Offset(markerX, dividerHeight / 2),
|
||||
end = Offset(width, dividerHeight / 2),
|
||||
strokeWidth = dividerHeight / 2
|
||||
)
|
||||
|
||||
drawCircle(
|
||||
color = markerColor,
|
||||
radius = markerSize.toPx() / 2,
|
||||
center = Offset(markerX, dividerHeight / 2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ScheduleItemPreview() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user