mirror of
https://github.com/n08i40k/polytechnic-android.git
synced 2025-12-06 09:47:48 +03:00
3.2.0
Изменённый дизайн.
This commit is contained in:
@@ -46,8 +46,8 @@ android {
|
||||
applicationId = "ru.n08i40k.polytechnic.next"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 28
|
||||
versionName = "3.1.1"
|
||||
versionCode = 29
|
||||
versionName = "3.2.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -136,6 +136,7 @@ dependencies {
|
||||
implementation(libs.kotlinx.datetime)
|
||||
|
||||
// default
|
||||
implementation(libs.androidx.runtime.tracing)
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
|
||||
@@ -2,9 +2,8 @@ package ru.n08i40k.polytechnic.next.ui.screen.schedule
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -24,6 +23,7 @@ import ru.n08i40k.polytechnic.next.ui.model.GroupUiState
|
||||
import ru.n08i40k.polytechnic.next.ui.model.GroupViewModel
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.LoadingContent
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.schedule.SchedulePager
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.schedule.UpdateInfo
|
||||
import ru.n08i40k.polytechnic.next.utils.rememberUpdatedLifecycleOwner
|
||||
|
||||
@Composable
|
||||
@@ -62,11 +62,10 @@ fun GroupScheduleScreen(viewModel: GroupViewModel) {
|
||||
) {
|
||||
when (uiState) {
|
||||
is GroupUiState.HasData -> {
|
||||
Column {
|
||||
Column(Modifier.padding(20.dp), Arrangement.spacedBy(10.dp)) {
|
||||
val data = uiState as GroupUiState.HasData
|
||||
|
||||
UpdateInfo(data.lastUpdateAt, data.cacheDate)
|
||||
Spacer(Modifier.height(10.dp))
|
||||
SchedulePager(data.group)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ package ru.n08i40k.polytechnic.next.ui.screen.schedule
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -24,6 +23,7 @@ import ru.n08i40k.polytechnic.next.ui.model.TeacherUiState
|
||||
import ru.n08i40k.polytechnic.next.ui.model.TeacherViewModel
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.LoadingContent
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.schedule.SchedulePager
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.schedule.UpdateInfo
|
||||
import ru.n08i40k.polytechnic.next.utils.rememberUpdatedLifecycleOwner
|
||||
|
||||
@Composable
|
||||
@@ -62,11 +62,10 @@ fun TeacherScheduleScreen(viewModel: TeacherViewModel) {
|
||||
) {
|
||||
when (uiState) {
|
||||
is TeacherUiState.HasData -> {
|
||||
Column {
|
||||
Column(Modifier.padding(20.dp), Arrangement.spacedBy(10.dp)) {
|
||||
val data = uiState as TeacherUiState.HasData
|
||||
|
||||
UpdateInfo(data.lastUpdateAt, data.cacheDate)
|
||||
Spacer(Modifier.height(10.dp))
|
||||
SchedulePager(data.teacher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -28,6 +29,7 @@ import ru.n08i40k.polytechnic.next.ui.model.SearchUiState
|
||||
import ru.n08i40k.polytechnic.next.ui.model.SearchViewModel
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.LoadingContent
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.schedule.SchedulePager
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.schedule.UpdateInfo
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.selector.TeacherNameSelector
|
||||
import ru.n08i40k.polytechnic.next.utils.rememberUpdatedLifecycleOwner
|
||||
|
||||
@@ -82,11 +84,10 @@ fun TeacherSearchScreen(viewModel: SearchViewModel) {
|
||||
|
||||
when (uiState) {
|
||||
is SearchUiState.HasData -> {
|
||||
Column {
|
||||
Column(Modifier.padding(20.dp), Arrangement.spacedBy(10.dp)) {
|
||||
val data = uiState as SearchUiState.HasData
|
||||
|
||||
UpdateInfo(data.lastUpdateAt, data.cacheDate)
|
||||
Spacer(Modifier.height(10.dp))
|
||||
SchedulePager(data.teacher)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -32,17 +31,12 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ExpandableCard(
|
||||
modifier: Modifier = Modifier,
|
||||
colors: CardColors = CardDefaults.cardColors(),
|
||||
border: BorderStroke = BorderStroke(
|
||||
Dp.Hairline,
|
||||
MaterialTheme.colorScheme.inverseSurface
|
||||
),
|
||||
expanded: Boolean = false,
|
||||
onExpandedChange: () -> Unit,
|
||||
title: @Composable () -> Unit,
|
||||
@@ -61,8 +55,7 @@ fun ExpandableCard(
|
||||
onExpandedChange()
|
||||
transitionState.targetState = expanded
|
||||
},
|
||||
colors = colors,
|
||||
border = border
|
||||
colors = colors
|
||||
) {
|
||||
Column {
|
||||
ExpandableCardHeader(title, transition)
|
||||
@@ -76,15 +69,10 @@ fun ExpandableCard(
|
||||
modifier: Modifier = Modifier,
|
||||
title: @Composable () -> Unit,
|
||||
colors: CardColors = CardDefaults.cardColors(),
|
||||
border: BorderStroke = BorderStroke(
|
||||
Dp.Hairline,
|
||||
MaterialTheme.colorScheme.inverseSurface
|
||||
),
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier,
|
||||
colors = colors,
|
||||
border = border
|
||||
colors = colors
|
||||
) {
|
||||
ExpandableCardHeader(title, null)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
package ru.n08i40k.polytechnic.next.ui.widgets.schedule
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
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.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeContent
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@@ -21,9 +25,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -33,8 +35,8 @@ import kotlinx.datetime.LocalDateTime
|
||||
import ru.n08i40k.polytechnic.next.R
|
||||
import ru.n08i40k.polytechnic.next.model.Day
|
||||
import ru.n08i40k.polytechnic.next.model.Lesson
|
||||
import ru.n08i40k.polytechnic.next.model.LessonType
|
||||
import ru.n08i40k.polytechnic.next.repository.schedule.impl.MockScheduleRepository
|
||||
import ru.n08i40k.polytechnic.next.ui.theme.AppTheme
|
||||
import ru.n08i40k.polytechnic.next.utils.dateTime
|
||||
import ru.n08i40k.polytechnic.next.utils.now
|
||||
|
||||
@@ -75,82 +77,42 @@ private fun getCurrentLessonIdx(day: Day?): Flow<Int> {
|
||||
return value
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun DayCardPreview() {
|
||||
AppTheme {
|
||||
Surface(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.windowInsetsPadding(WindowInsets.safeContent.only(WindowInsetsSides.Top))
|
||||
) {
|
||||
DayCard(Modifier, MockScheduleRepository.exampleTeacher.days[0]) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DayCard(
|
||||
modifier: Modifier = Modifier,
|
||||
day: Day = MockScheduleRepository.exampleTeacher.days[0],
|
||||
onLessonClick: (Lesson) -> Unit = {},
|
||||
day: Day,
|
||||
onLessonClick: (Lesson) -> Unit,
|
||||
) {
|
||||
val offset = remember(day) { getDayOffset(day) }
|
||||
|
||||
val defaultCardColors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
)
|
||||
val customCardColors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||
)
|
||||
val noneCardColors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
)
|
||||
val examCardColors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onErrorContainer,
|
||||
)
|
||||
|
||||
Card(
|
||||
modifier,
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = when (offset) {
|
||||
DayOffset.TODAY -> MaterialTheme.colorScheme.primaryContainer
|
||||
else -> MaterialTheme.colorScheme.secondaryContainer
|
||||
}
|
||||
),
|
||||
border = BorderStroke(1.dp, MaterialTheme.colorScheme.inverseSurface)
|
||||
) {
|
||||
Text(
|
||||
day.name,
|
||||
Modifier.fillMaxWidth(),
|
||||
fontWeight = FontWeight.Bold,
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainerLowest
|
||||
)
|
||||
|
||||
day.street?.let {
|
||||
Text(
|
||||
it,
|
||||
Modifier.fillMaxWidth(),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
if (offset != DayOffset.OTHER) {
|
||||
Text(
|
||||
stringResource(
|
||||
when (offset) {
|
||||
DayOffset.YESTERDAY -> R.string.yesterday
|
||||
DayOffset.TODAY -> R.string.today
|
||||
DayOffset.TOMORROW -> R.string.tomorrow
|
||||
DayOffset.OTHER -> throw RuntimeException()
|
||||
}
|
||||
),
|
||||
Modifier.fillMaxWidth(),
|
||||
fontWeight = FontWeight.Bold,
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
|
||||
) {
|
||||
val currentLessonIndex by getCurrentLessonIdx(if (offset == DayOffset.TODAY) day else null)
|
||||
.collectAsStateWithLifecycle(0)
|
||||
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(10.dp),
|
||||
Arrangement.spacedBy(0.5.dp)
|
||||
) {
|
||||
if (day.lessons.isEmpty()) {
|
||||
@@ -159,36 +121,10 @@ fun DayCard(
|
||||
}
|
||||
|
||||
for (lessonIndex in day.lessons.indices) {
|
||||
HorizontalDivider(
|
||||
thickness = 1.dp,
|
||||
color = MaterialTheme.colorScheme.inversePrimary
|
||||
)
|
||||
|
||||
val lesson = day.lessons[lessonIndex]
|
||||
|
||||
val cardColors = when (lesson.type) {
|
||||
LessonType.DEFAULT -> defaultCardColors
|
||||
LessonType.ADDITIONAL -> noneCardColors
|
||||
LessonType.BREAK -> noneCardColors
|
||||
LessonType.CONSULTATION -> customCardColors
|
||||
LessonType.INDEPENDENT_WORK -> customCardColors
|
||||
LessonType.EXAM -> examCardColors
|
||||
LessonType.EXAM_WITH_GRADE -> examCardColors
|
||||
LessonType.EXAM_DEFAULT -> examCardColors
|
||||
}
|
||||
|
||||
Box(
|
||||
Modifier
|
||||
.clickable { onLessonClick(lesson) }
|
||||
.background(cardColors.containerColor)
|
||||
) {
|
||||
val modifier =
|
||||
if (lessonIndex == currentLessonIndex)
|
||||
Modifier.border(BorderStroke(1.dp, MaterialTheme.colorScheme.error))
|
||||
else
|
||||
Modifier
|
||||
|
||||
LessonRow(modifier, lesson, cardColors)
|
||||
Box(Modifier.clickable { onLessonClick(lesson) }) {
|
||||
LessonRow(modifier, lesson, lessonIndex == currentLessonIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,47 @@
|
||||
package ru.n08i40k.polytechnic.next.ui.widgets.schedule
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeContent
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.text.BasicText
|
||||
import androidx.compose.material3.CardColors
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.n08i40k.polytechnic.next.R
|
||||
import ru.n08i40k.polytechnic.next.model.Lesson
|
||||
import ru.n08i40k.polytechnic.next.model.LessonType
|
||||
import ru.n08i40k.polytechnic.next.repository.schedule.impl.MockScheduleRepository
|
||||
import ru.n08i40k.polytechnic.next.ui.theme.AppTheme
|
||||
import ru.n08i40k.polytechnic.next.utils.dayMinutes
|
||||
import ru.n08i40k.polytechnic.next.utils.fmtAsClock
|
||||
|
||||
@@ -42,31 +55,51 @@ private fun fmtTime(start: Int, end: Int, format: TimeFormat): ArrayList<String>
|
||||
return when (format) {
|
||||
TimeFormat.CLOCK -> arrayListOf(start.fmtAsClock(), end.fmtAsClock())
|
||||
TimeFormat.DURATION -> arrayListOf(
|
||||
"${end - start} ${stringResource(R.string.minutes)}"
|
||||
"${end - start} ${stringResource(R.string.minutes_full)}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, showSystemUi = true)
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun LessonRowPreview() {
|
||||
AppTheme {
|
||||
Surface(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.windowInsetsPadding(WindowInsets.safeContent.only(WindowInsetsSides.Top))
|
||||
) {
|
||||
LessonRow(Modifier, MockScheduleRepository.exampleGroup.days[0].lessons[6], true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LessonRow(
|
||||
modifier: Modifier = Modifier,
|
||||
lesson: Lesson = MockScheduleRepository.exampleGroup.days[0].lessons[0],
|
||||
colors: CardColors = CardDefaults.cardColors()
|
||||
lesson: Lesson,
|
||||
current: Boolean
|
||||
) {
|
||||
val verticalPadding = when (lesson.type) {
|
||||
LessonType.BREAK -> 2.5.dp
|
||||
else -> 5.dp
|
||||
}
|
||||
var time = fmtTime(
|
||||
lesson.time.start.dayMinutes,
|
||||
lesson.time.end.dayMinutes,
|
||||
if (lesson.type == LessonType.BREAK) TimeFormat.DURATION else TimeFormat.CLOCK
|
||||
)
|
||||
|
||||
val timeFormat = when (lesson.type) {
|
||||
LessonType.BREAK -> TimeFormat.DURATION
|
||||
else -> TimeFormat.CLOCK
|
||||
}
|
||||
if (lesson.type == LessonType.BREAK) {
|
||||
Box(Modifier.fillMaxWidth(), Alignment.Center) {
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.surfaceContainerHighest)
|
||||
Text(
|
||||
time[0],
|
||||
Modifier
|
||||
.background(MaterialTheme.colorScheme.surfaceContainerLowest)
|
||||
.padding(5.dp, 0.dp),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.surfaceContainerHighest,
|
||||
)
|
||||
}
|
||||
|
||||
val contentColor = when (lesson.type) {
|
||||
LessonType.BREAK -> colors.disabledContentColor
|
||||
else -> colors.contentColor
|
||||
return
|
||||
}
|
||||
|
||||
// магические вычисления))
|
||||
@@ -78,120 +111,184 @@ fun LessonRow(
|
||||
|
||||
Box(modifier) {
|
||||
Row(
|
||||
Modifier.padding(10.dp, verticalPadding * rangeSize),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
Modifier.padding(10.dp, 5.dp * rangeSize),
|
||||
Arrangement.spacedBy(15.dp),
|
||||
Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
when (range) {
|
||||
null -> " "
|
||||
else -> {
|
||||
if (range[0] == range[1])
|
||||
" ${range[0]} "
|
||||
else
|
||||
"${range[0]}-${range[1]}"
|
||||
}
|
||||
},
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = contentColor
|
||||
)
|
||||
|
||||
Spacer(Modifier.width(5.dp))
|
||||
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
val timeWidth = textMeasurer.measure(
|
||||
text = "00:00 ",
|
||||
text = "00:00",
|
||||
style = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace)
|
||||
)
|
||||
|
||||
Column(
|
||||
Modifier.width(with(LocalDensity.current) { timeWidth.size.width.toDp() }),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
Modifier
|
||||
.width(with(LocalDensity.current) { timeWidth.size.width.toDp() + 1.dp }),
|
||||
Arrangement.spacedBy(5.dp),
|
||||
Alignment.CenterHorizontally
|
||||
) {
|
||||
var time = fmtTime(
|
||||
lesson.time.start.dayMinutes,
|
||||
lesson.time.end.dayMinutes,
|
||||
timeFormat
|
||||
)
|
||||
|
||||
Text(time[0], color = contentColor, fontFamily = FontFamily.Monospace, maxLines = 1)
|
||||
if (lesson.type != LessonType.BREAK)
|
||||
Column {
|
||||
Text(
|
||||
time[0],
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.W600,
|
||||
style = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
Text(
|
||||
time[1],
|
||||
color = contentColor,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
maxLines = 1
|
||||
fontWeight = FontWeight.W600,
|
||||
style = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(Modifier.width(5.dp))
|
||||
|
||||
Row(Modifier.fillMaxWidth(), Arrangement.SpaceBetween, Alignment.CenterVertically) {
|
||||
Column(Modifier.weight(1f)) {
|
||||
// FIXME: Очень странный метод отсеивания, может что-нибудь на замену сделать?
|
||||
if (lesson.type.value > LessonType.BREAK.value) {
|
||||
Text(
|
||||
when (lesson.type) {
|
||||
LessonType.CONSULTATION -> stringResource(R.string.lesson_type_consultation)
|
||||
LessonType.INDEPENDENT_WORK -> stringResource(R.string.lesson_type_independent_work)
|
||||
LessonType.EXAM -> stringResource(R.string.lesson_type_exam)
|
||||
LessonType.EXAM_WITH_GRADE -> stringResource(R.string.lesson_type_exam_with_grade)
|
||||
LessonType.EXAM_DEFAULT -> stringResource(R.string.lesson_type_exam_default)
|
||||
else -> throw RuntimeException("Unknown lesson type!")
|
||||
},
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = contentColor
|
||||
)
|
||||
}
|
||||
if (range != null) {
|
||||
HorizontalDivider(
|
||||
Modifier.width(32.dp),
|
||||
1.dp,
|
||||
MaterialTheme.colorScheme.inverseSurface
|
||||
)
|
||||
|
||||
Text(
|
||||
lesson.name ?: stringResource(R.string.lesson_type_break),
|
||||
fontWeight = FontWeight.Medium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = contentColor
|
||||
if (range[0] == range[1])
|
||||
" ${range[0]} "
|
||||
else
|
||||
"${range[0]}-${range[1]}",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
|
||||
if (lesson.group != null) {
|
||||
Text(
|
||||
lesson.group,
|
||||
color = contentColor,
|
||||
fontWeight = FontWeight.Medium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
for (subGroup in lesson.subGroups) {
|
||||
Text(
|
||||
subGroup.teacher,
|
||||
color = contentColor,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column(Modifier.wrapContentWidth()) {
|
||||
if (lesson.subGroups.size != 1) {
|
||||
BasicText("")
|
||||
|
||||
if (lesson.group != null)
|
||||
BasicText("")
|
||||
}
|
||||
|
||||
for (subGroup in lesson.subGroups) {
|
||||
Text(
|
||||
subGroup.cabinet,
|
||||
color = contentColor,
|
||||
maxLines = 1,
|
||||
fontFamily = FontFamily.Monospace
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerticalDivider(
|
||||
Modifier.height(42.dp),
|
||||
1.dp,
|
||||
if (current)
|
||||
MaterialTheme.colorScheme.primary
|
||||
else
|
||||
MaterialTheme.colorScheme.inverseSurface
|
||||
)
|
||||
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(
|
||||
lesson.name!!,
|
||||
fontWeight = FontWeight.W600,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
|
||||
|
||||
// FIXME: Очень странный метод отсеивания, может что-нибудь на замену сделать?
|
||||
if (lesson.type.value > LessonType.BREAK.value) {
|
||||
Text(
|
||||
when (lesson.type) {
|
||||
LessonType.CONSULTATION -> stringResource(R.string.lesson_type_consultation)
|
||||
LessonType.INDEPENDENT_WORK -> stringResource(R.string.lesson_type_independent_work)
|
||||
LessonType.EXAM -> stringResource(R.string.lesson_type_exam)
|
||||
LessonType.EXAM_WITH_GRADE -> stringResource(R.string.lesson_type_exam_with_grade)
|
||||
LessonType.EXAM_DEFAULT -> stringResource(R.string.lesson_type_exam_default)
|
||||
else -> throw RuntimeException("Unknown lesson type!")
|
||||
},
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
fontWeight = FontWeight.W600,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SmallTextWithIcon(
|
||||
@DrawableRes iconId: Int,
|
||||
contentDescription: String,
|
||||
text: String
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
painterResource(iconId),
|
||||
contentDescription,
|
||||
Modifier.size(12.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text,
|
||||
fontWeight = FontWeight.W400,
|
||||
style = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (lesson.group != null) {
|
||||
Row {
|
||||
Spacer(Modifier.size(5.dp))
|
||||
|
||||
SmallTextWithIcon(
|
||||
R.drawable.ic_group,
|
||||
"Group",
|
||||
lesson.group
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(5.dp),
|
||||
Arrangement.SpaceBetween,
|
||||
Alignment.CenterVertically
|
||||
) {
|
||||
lesson
|
||||
.subGroups
|
||||
.sortedBy { it.number }
|
||||
.forEachIndexed { subGroupIdx, subGroup ->
|
||||
if (subGroupIdx > 0) {
|
||||
VerticalDivider(
|
||||
Modifier.height(25.dp), 1.dp,
|
||||
MaterialTheme.colorScheme.inverseSurface
|
||||
)
|
||||
}
|
||||
|
||||
// FIXME: тупая проверка
|
||||
if (subGroup.teacher == "Только у другой") {
|
||||
Text(
|
||||
stringResource(
|
||||
if (subGroup.number == 1)
|
||||
R.string.only_for_second
|
||||
else
|
||||
R.string.only_for_first
|
||||
),
|
||||
fontWeight = FontWeight.W400,
|
||||
style = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
Column {
|
||||
val cabinet =
|
||||
if (subGroup.cabinet.toIntOrNull() == null)
|
||||
subGroup.cabinet
|
||||
else
|
||||
"№${subGroup.cabinet}"
|
||||
|
||||
SmallTextWithIcon(
|
||||
R.drawable.ic_cabinet,
|
||||
"Cabinet",
|
||||
cabinet
|
||||
)
|
||||
|
||||
SmallTextWithIcon(
|
||||
R.drawable.ic_teacher,
|
||||
"Teacher",
|
||||
subGroup.teacher
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,53 @@
|
||||
package ru.n08i40k.polytechnic.next.ui.widgets.schedule
|
||||
|
||||
import androidx.compose.animation.Animatable
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeContent
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
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.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.lerp
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import ru.n08i40k.polytechnic.next.R
|
||||
import ru.n08i40k.polytechnic.next.model.GroupOrTeacher
|
||||
import ru.n08i40k.polytechnic.next.model.Lesson
|
||||
import ru.n08i40k.polytechnic.next.model.LessonType
|
||||
import ru.n08i40k.polytechnic.next.repository.schedule.impl.MockScheduleRepository
|
||||
import ru.n08i40k.polytechnic.next.ui.theme.AppTheme
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.NotificationCard
|
||||
import ru.n08i40k.polytechnic.next.utils.dateTime
|
||||
import ru.n08i40k.polytechnic.next.utils.now
|
||||
@@ -39,9 +63,31 @@ private fun isScheduleOutdated(schedule: GroupOrTeacher): Boolean {
|
||||
return nowDateTime > lastLesson.time.end.dateTime
|
||||
}
|
||||
|
||||
@Preview(showSystemUi = true)
|
||||
@PreviewLightDark()
|
||||
@Composable
|
||||
fun SchedulePager(schedule: GroupOrTeacher = MockScheduleRepository.exampleTeacher) {
|
||||
private fun SchedulePagerPreview() {
|
||||
AppTheme {
|
||||
Surface(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.windowInsetsPadding(WindowInsets.safeContent.only(WindowInsetsSides.Top))
|
||||
) {
|
||||
SchedulePager(MockScheduleRepository.exampleTeacher)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val weekList = listOf(
|
||||
R.string.week_bar_monday,
|
||||
R.string.week_bar_tuesday,
|
||||
R.string.week_bar_wednesday,
|
||||
R.string.week_bar_thursday,
|
||||
R.string.week_bar_friday,
|
||||
R.string.week_bar_saturday,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SchedulePager(schedule: GroupOrTeacher) {
|
||||
val pagerState = rememberPagerState(
|
||||
initialPage = (schedule.currentIdx ?: (schedule.days.size - 1)).coerceAtLeast(0),
|
||||
pageCount = { schedule.days.size }
|
||||
@@ -49,16 +95,88 @@ fun SchedulePager(schedule: GroupOrTeacher = MockScheduleRepository.exampleTeach
|
||||
|
||||
var dialogLesson by remember { mutableStateOf<WeakReference<Lesson>?>(null) }
|
||||
|
||||
Column {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth(),
|
||||
Arrangement.spacedBy(20.dp)
|
||||
) {
|
||||
if (isScheduleOutdated(schedule))
|
||||
NotificationCard(Level.WARNING, stringResource(R.string.outdated_schedule))
|
||||
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainerLowest
|
||||
)
|
||||
) {
|
||||
Row(Modifier.fillMaxWidth(), Arrangement.spacedBy(5.dp)) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
for (i in 0..5) {
|
||||
val primaryContainerColor = MaterialTheme.colorScheme.primaryContainer
|
||||
|
||||
val onPrimaryContainerColor = MaterialTheme.colorScheme.onPrimaryContainer
|
||||
val onSurfaceColor = MaterialTheme.colorScheme.onSurface
|
||||
|
||||
val containerColor = remember {
|
||||
Animatable(
|
||||
if (pagerState.currentPage == i) primaryContainerColor
|
||||
else Color.Transparent
|
||||
)
|
||||
}
|
||||
val contentColor = remember {
|
||||
Animatable(
|
||||
if (pagerState.currentPage == i) onPrimaryContainerColor
|
||||
else onSurfaceColor
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(pagerState, pagerState.currentPage) {
|
||||
containerColor.animateTo(
|
||||
if (pagerState.currentPage == i) primaryContainerColor
|
||||
else Color.Transparent
|
||||
)
|
||||
|
||||
contentColor.animateTo(
|
||||
if (pagerState.currentPage == i) onPrimaryContainerColor
|
||||
else onSurfaceColor
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.clip(RoundedCornerShape(20))
|
||||
.background(containerColor.value)
|
||||
.clickable { coroutineScope.launch { pagerState.animateScrollToPage(i) } },
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
stringResource(weekList[i]),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = contentColor.value
|
||||
)
|
||||
|
||||
Text(
|
||||
schedule.days[i].date.dateTime.date.dayOfMonth.toString(),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
fontWeight = FontWeight.W600,
|
||||
color = contentColor.value
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalPager(
|
||||
pagerState,
|
||||
Modifier
|
||||
.height(600.dp)
|
||||
.padding(top = 5.dp),
|
||||
PaddingValues(horizontal = 7.dp),
|
||||
.height(600.dp),
|
||||
verticalAlignment = Alignment.Top
|
||||
) { page ->
|
||||
DayCard(
|
||||
@@ -68,7 +186,7 @@ fun SchedulePager(schedule: GroupOrTeacher = MockScheduleRepository.exampleTeach
|
||||
).absoluteValue
|
||||
|
||||
lerp(
|
||||
start = 1f, stop = 0.95f, fraction = 1f - offset.coerceIn(0f, 1f)
|
||||
start = 1f, stop = 0.95f, fraction = offset.coerceIn(0f, 1f)
|
||||
).also { scale ->
|
||||
scaleX = scale
|
||||
scaleY = scale
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.n08i40k.polytechnic.next.ui.screen.schedule
|
||||
package ru.n08i40k.polytechnic.next.ui.widgets.schedule
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -21,20 +23,19 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.n08i40k.polytechnic.next.CacheDate
|
||||
import ru.n08i40k.polytechnic.next.R
|
||||
import ru.n08i40k.polytechnic.next.ui.screen.schedule.PaskhalkoDialog
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.ExpandableCard
|
||||
import ru.n08i40k.polytechnic.next.ui.widgets.ExpandableCardTitle
|
||||
import ru.n08i40k.polytechnic.next.utils.*
|
||||
import java.util.Date
|
||||
|
||||
val expanded = mutableStateOf(false)
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun UpdateInfo(
|
||||
lastUpdateAt: Long = 0,
|
||||
cacheDate: CacheDate = CacheDate.newBuilder().build()
|
||||
) {
|
||||
var expanded by remember { expanded }
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
val format = "HH:mm:ss dd.MM.yyyy"
|
||||
|
||||
@@ -44,6 +45,7 @@ fun UpdateInfo(
|
||||
|
||||
ExpandableCard(
|
||||
expanded = expanded,
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainerLowest),
|
||||
onExpandedChange = { expanded = !expanded },
|
||||
title = { ExpandableCardTitle(stringResource(R.string.update_info_header)) }
|
||||
) {
|
||||
9
app/src/main/res/drawable/ic_cabinet.xml
Normal file
9
app/src/main/res/drawable/ic_cabinet.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M120,840v-80h80v-640h400v40h160v600h80v80L680,840v-600h-80v600L120,840ZM280,200v560,-560ZM440,520q17,0 28.5,-11.5T480,480q0,-17 -11.5,-28.5T440,440q-17,0 -28.5,11.5T400,480q0,17 11.5,28.5T440,520ZM280,760h240v-560L280,200v560Z"
|
||||
android:fillColor="#e8eaed"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_group.xml
Normal file
9
app/src/main/res/drawable/ic_group.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M96,768v-92q0,-25.78 12.5,-47.39T143,594q54,-32 114.5,-49T384,528q66,0 126.5,17T625,594q22,13 34.5,34.61T672,676v92L96,768ZM744,768v-92q0,-42 -19.5,-78T672,539q39,8 75.5,21.5T817,594q22,13 34.5,34.67Q864,650.35 864,676v92L744,768ZM384,480q-60,0 -102,-42t-42,-102q0,-60 42,-102t102,-42q60,0 102,42t42,102q0,60 -42,102t-102,42ZM720,336q0,60 -42,102t-102,42q-8,0 -15,-0.5t-15,-2.5q25,-29 39.5,-64.5T600,336q0,-41 -14.5,-76.5T546,195q8,-2 15,-2.5t15,-0.5q60,0 102,42t42,102ZM168,696h432v-20q0,-6.47 -3.03,-11.76 -3.02,-5.3 -7.97,-8.24 -47,-27 -99,-41.5T384,600q-54,0 -106,14t-99,42q-4.95,2.83 -7.98,7.91 -3.02,5.09 -3.02,12L168,696ZM384.21,408Q414,408 435,386.79t21,-51Q456,306 434.79,285t-51,-21Q354,264 333,285.21t-21,51Q312,366 333.21,387t51,21ZM384,696ZM384,336Z"
|
||||
android:fillColor="#e8eaed"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_teacher.xml
Normal file
9
app/src/main/res/drawable/ic_teacher.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M480,840 L200,688v-240L40,360l440,-240 440,240v320h-80v-276l-80,44v240L480,840ZM480,508 L754,360 480,212 206,360 480,508ZM480,749 L680,641v-151L480,600 280,490v151l200,108ZM480,508ZM480,598ZM480,598Z"
|
||||
android:fillColor="#e8eaed"/>
|
||||
</vector>
|
||||
@@ -67,7 +67,7 @@
|
||||
<string name="auth_error_disallowed_role">Пожалуйста, используйте другую роль.</string>
|
||||
<string name="sign_in_manual">По имени пользователя</string>
|
||||
<string name="updater_support_end">Поддержка версий ниже %1$s прекращена!</string>
|
||||
<string name="last_server_schedule_update">Последнее обновление расписания</string>
|
||||
<string name="last_server_schedule_update">Расписание</string>
|
||||
<string name="teacher_name">ФИО преподавателя</string>
|
||||
<string name="updater_body">Желаете ли вы обновиться до последней версии?</string>
|
||||
<string name="updater_new_version">Вышла новая версия приложения!</string>
|
||||
@@ -76,8 +76,8 @@
|
||||
<string name="updater_update">ОБНОВИТЬ</string>
|
||||
<string name="updater_suppress">ЗАГЛУШИТЬ</string>
|
||||
<string name="update_info_header">Дополнительная информация</string>
|
||||
<string name="last_local_update">Последнее локальное обновление</string>
|
||||
<string name="last_server_cache_update">Последнее обновление кеша</string>
|
||||
<string name="last_local_update">Локально</string>
|
||||
<string name="last_server_cache_update">Кеш</string>
|
||||
<string name="download_update">Скачать обновление</string>
|
||||
<string name="telegram_channel">Телеграм канал</string>
|
||||
<string name="schedule_update_title">Расписание обновлено!</string>
|
||||
@@ -107,4 +107,13 @@
|
||||
<string name="extra_info_duration">"Длительность: "</string>
|
||||
<string name="extra_info_duration_second">С %1$s до %2$s (%3$d ч. %4$d мин.)</string>
|
||||
<string name="extra_info_type">"Тип: "</string>
|
||||
<string name="minutes_full">минут</string>
|
||||
<string name="only_for_second">Только у второй</string>
|
||||
<string name="only_for_first">Только у первой</string>
|
||||
<string name="week_bar_monday">Пн</string>
|
||||
<string name="week_bar_tuesday">Вт</string>
|
||||
<string name="week_bar_wednesday">Ср</string>
|
||||
<string name="week_bar_thursday">Чт</string>
|
||||
<string name="week_bar_friday">Пт</string>
|
||||
<string name="week_bar_saturday">Сб</string>
|
||||
</resources>
|
||||
@@ -107,4 +107,13 @@
|
||||
<string name="extra_info_duration">"Duration: "</string>
|
||||
<string name="extra_info_duration_second">From %1$s to %2$s (%3$d h. %4$d min.)</string>
|
||||
<string name="extra_info_type">"Type: "</string>
|
||||
<string name="minutes_full">minutes</string>
|
||||
<string name="only_for_second">Only for second</string>
|
||||
<string name="only_for_first">Only for first</string>
|
||||
<string name="week_bar_tuesday">Tue</string>
|
||||
<string name="week_bar_wednesday">Wed</string>
|
||||
<string name="week_bar_thursday">Thu</string>
|
||||
<string name="week_bar_friday">Fri</string>
|
||||
<string name="week_bar_saturday">Sat</string>
|
||||
<string name="week_bar_monday">Mon</string>
|
||||
</resources>
|
||||
@@ -16,6 +16,7 @@ hiltAndroidCompiler = "2.55"
|
||||
hiltNavigationCompose = "1.2.0"
|
||||
kotlinxSerializationJson = "1.8.0"
|
||||
protobufLite = "3.0.1"
|
||||
runtimeTracing = "1.7.8"
|
||||
volley = "1.2.1"
|
||||
datastore = "1.1.3"
|
||||
navigationCompose = "2.8.9"
|
||||
@@ -26,6 +27,7 @@ vkid = "2.2.2"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
androidx-runtime-tracing = { module = "androidx.compose.runtime:runtime-tracing", version.ref = "runtimeTracing" }
|
||||
desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
|
||||
Reference in New Issue
Block a user