mirror of
https://github.com/n08i40k/polytechnic-android.git
synced 2025-12-06 09:47:48 +03:00
2.2.1
Теперь регулярное выражение для парсинга ссылки на расписание получается с сервера. 2.2.0 Отображение дополнительного типа пары. Отображение улицы, на которой будут проходить пары, если указана.
This commit is contained in:
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@@ -1,3 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
<list size="2">
|
<list size="2">
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ android {
|
|||||||
applicationId = "ru.n08i40k.polytechnic.next"
|
applicationId = "ru.n08i40k.polytechnic.next"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 20
|
versionCode = 22
|
||||||
versionName = "2.1.0"
|
versionName = "2.2.1"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package ru.n08i40k.polytechnic.next.data
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.google.firebase.Firebase
|
||||||
|
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
|
||||||
|
import com.google.firebase.remoteconfig.remoteConfig
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
@@ -10,11 +13,11 @@ import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
|||||||
import ru.n08i40k.polytechnic.next.data.cache.impl.FakeNetworkCacheRepository
|
import ru.n08i40k.polytechnic.next.data.cache.impl.FakeNetworkCacheRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.cache.impl.LocalNetworkCacheRepository
|
import ru.n08i40k.polytechnic.next.data.cache.impl.LocalNetworkCacheRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.schedule.ScheduleRepository
|
import ru.n08i40k.polytechnic.next.data.schedule.ScheduleRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl.FakeScheduleReplacerRepository
|
|
||||||
import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleRepository
|
import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl.RemoteScheduleReplacerRepository
|
|
||||||
import ru.n08i40k.polytechnic.next.data.schedule.impl.RemoteScheduleRepository
|
import ru.n08i40k.polytechnic.next.data.schedule.impl.RemoteScheduleRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.ScheduleReplacerRepository
|
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.ScheduleReplacerRepository
|
||||||
|
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl.FakeScheduleReplacerRepository
|
||||||
|
import ru.n08i40k.polytechnic.next.data.scheduleReplacer.impl.RemoteScheduleReplacerRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
|
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.users.impl.FakeProfileRepository
|
import ru.n08i40k.polytechnic.next.data.users.impl.FakeProfileRepository
|
||||||
import ru.n08i40k.polytechnic.next.data.users.impl.RemoteProfileRepository
|
import ru.n08i40k.polytechnic.next.data.users.impl.RemoteProfileRepository
|
||||||
@@ -30,6 +33,8 @@ interface AppContainer {
|
|||||||
val scheduleReplacerRepository: ScheduleReplacerRepository
|
val scheduleReplacerRepository: ScheduleReplacerRepository
|
||||||
|
|
||||||
val profileRepository: ProfileRepository
|
val profileRepository: ProfileRepository
|
||||||
|
|
||||||
|
val remoteConfig: FirebaseRemoteConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockAppContainer(override val applicationContext: Context) : AppContainer {
|
class MockAppContainer(override val applicationContext: Context) : AppContainer {
|
||||||
@@ -44,6 +49,9 @@ class MockAppContainer(override val applicationContext: Context) : AppContainer
|
|||||||
|
|
||||||
override val profileRepository: ProfileRepository
|
override val profileRepository: ProfileRepository
|
||||||
by lazy { FakeProfileRepository() }
|
by lazy { FakeProfileRepository() }
|
||||||
|
|
||||||
|
override val remoteConfig: FirebaseRemoteConfig
|
||||||
|
by lazy { Firebase.remoteConfig }
|
||||||
}
|
}
|
||||||
|
|
||||||
class RemoteAppContainer(override val applicationContext: Context) : AppContainer {
|
class RemoteAppContainer(override val applicationContext: Context) : AppContainer {
|
||||||
@@ -58,6 +66,9 @@ class RemoteAppContainer(override val applicationContext: Context) : AppContaine
|
|||||||
|
|
||||||
override val profileRepository: ProfileRepository
|
override val profileRepository: ProfileRepository
|
||||||
by lazy { RemoteProfileRepository(applicationContext) }
|
by lazy { RemoteProfileRepository(applicationContext) }
|
||||||
|
|
||||||
|
override val remoteConfig: FirebaseRemoteConfig
|
||||||
|
by lazy { Firebase.remoteConfig }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ data class Day(
|
|||||||
@SerialName("date")
|
@SerialName("date")
|
||||||
private val dateMillis: Long,
|
private val dateMillis: Long,
|
||||||
|
|
||||||
val lessons: List<Lesson>
|
val lessons: List<Lesson>,
|
||||||
|
|
||||||
|
val street: String? = null
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
constructor(name: String, date: Instant, lessons: List<Lesson>) : this(
|
constructor(name: String, date: Instant, lessons: List<Lesson>) : this(
|
||||||
name, date.toEpochMilliseconds(), lessons
|
name, date.toEpochMilliseconds(), lessons
|
||||||
|
|||||||
@@ -13,5 +13,9 @@ private class LessonTypeIntSerializer : EnumAsIntSerializer<LessonType>(
|
|||||||
enum class LessonType(val value: Int) {
|
enum class LessonType(val value: Int) {
|
||||||
DEFAULT(0),
|
DEFAULT(0),
|
||||||
ADDITIONAL(1),
|
ADDITIONAL(1),
|
||||||
BREAK(2)
|
BREAK(2),
|
||||||
|
CONSULTATION(3),
|
||||||
|
INDEPENDENT_WORK(4),
|
||||||
|
EXAM(5),
|
||||||
|
EXAM_WITH_GRADE(6),
|
||||||
}
|
}
|
||||||
@@ -33,11 +33,6 @@ open class CachedRequest(
|
|||||||
}, errorListener) {
|
}, errorListener) {
|
||||||
private val appContainer: AppContainer = (context as PolytechnicApplication).container
|
private val appContainer: AppContainer = (context as PolytechnicApplication).container
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val REGEX: String = "<a href=\"(/\\d{4}/[\\w\\-_]+\\.xls)\">"
|
|
||||||
val pattern: Pattern = Pattern.compile(REGEX, Pattern.MULTILINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun getXlsUrl(): MyResult<String> = withContext(Dispatchers.IO) {
|
private suspend fun getXlsUrl(): MyResult<String> = withContext(Dispatchers.IO) {
|
||||||
val mainPageFuture = RequestFuture.newFuture<String>()
|
val mainPageFuture = RequestFuture.newFuture<String>()
|
||||||
val request = StringRequest(
|
val request = StringRequest(
|
||||||
@@ -54,6 +49,11 @@ open class CachedRequest(
|
|||||||
|
|
||||||
val pageData = (response as MyResult.Success).data
|
val pageData = (response as MyResult.Success).data
|
||||||
|
|
||||||
|
val remoteConfig = (context.applicationContext as PolytechnicApplication).container.remoteConfig
|
||||||
|
|
||||||
|
val pattern: Pattern =
|
||||||
|
Pattern.compile(remoteConfig.getString("linkParserRegex"), Pattern.MULTILINE)
|
||||||
|
|
||||||
val matcher = pattern.matcher(pageData)
|
val matcher = pattern.matcher(pageData)
|
||||||
if (!matcher.find())
|
if (!matcher.find())
|
||||||
return@withContext MyResult.Failure(RuntimeException("Required url not found!"))
|
return@withContext MyResult.Failure(RuntimeException("Required url not found!"))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class ScheduleGet(
|
|||||||
) : CachedRequest(
|
) : CachedRequest(
|
||||||
context,
|
context,
|
||||||
Method.GET,
|
Method.GET,
|
||||||
"v2/schedule/group",
|
"v3/schedule/group",
|
||||||
{ listener.onResponse(Json.decodeFromString(it)) },
|
{ listener.onResponse(Json.decodeFromString(it)) },
|
||||||
errorListener
|
errorListener
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ScheduleGetTeacher(
|
|||||||
) : CachedRequest(
|
) : CachedRequest(
|
||||||
context,
|
context,
|
||||||
Method.GET,
|
Method.GET,
|
||||||
"v2/schedule/teacher/$teacher",
|
"v3/schedule/teacher/$teacher",
|
||||||
{ listener.onResponse(Json.decodeFromString(it)) },
|
{ listener.onResponse(Json.decodeFromString(it)) },
|
||||||
errorListener
|
errorListener
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ScheduleUpdate(
|
|||||||
) : AuthorizedRequest(
|
) : AuthorizedRequest(
|
||||||
context,
|
context,
|
||||||
Method.PATCH,
|
Method.PATCH,
|
||||||
"v2/schedule/update-download-url",
|
"v4/schedule/update-download-url",
|
||||||
{ listener.onResponse(Json.decodeFromString(it)) },
|
{ listener.onResponse(Json.decodeFromString(it)) },
|
||||||
errorListener
|
errorListener
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ import androidx.work.OneTimeWorkRequestBuilder
|
|||||||
import androidx.work.PeriodicWorkRequest
|
import androidx.work.PeriodicWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import com.google.firebase.Firebase
|
|
||||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
|
|
||||||
import com.google.firebase.remoteconfig.remoteConfig
|
|
||||||
import com.google.firebase.remoteconfig.remoteConfigSettings
|
import com.google.firebase.remoteconfig.remoteConfigSettings
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@@ -44,8 +41,6 @@ import java.util.concurrent.TimeUnit
|
|||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
|
|
||||||
|
|
||||||
private val configSettings = remoteConfigSettings {
|
private val configSettings = remoteConfigSettings {
|
||||||
minimumFetchIntervalInSeconds = 3600
|
minimumFetchIntervalInSeconds = 3600
|
||||||
}
|
}
|
||||||
@@ -118,6 +113,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupFirebaseConfig() {
|
private fun setupFirebaseConfig() {
|
||||||
|
val remoteConfig = (application as PolytechnicApplication).container.remoteConfig
|
||||||
|
|
||||||
remoteConfig.setConfigSettingsAsync(configSettings)
|
remoteConfig.setConfigSettingsAsync(configSettings)
|
||||||
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
|
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ import ru.n08i40k.polytechnic.next.PolytechnicApplication
|
|||||||
import ru.n08i40k.polytechnic.next.R
|
import ru.n08i40k.polytechnic.next.R
|
||||||
import ru.n08i40k.polytechnic.next.model.UserRole
|
import ru.n08i40k.polytechnic.next.model.UserRole
|
||||||
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
|
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
|
||||||
import ru.n08i40k.polytechnic.next.ui.MainActivity
|
|
||||||
import ru.n08i40k.polytechnic.next.ui.icons.AppIcons
|
import ru.n08i40k.polytechnic.next.ui.icons.AppIcons
|
||||||
import ru.n08i40k.polytechnic.next.ui.icons.appicons.Filled
|
import ru.n08i40k.polytechnic.next.ui.icons.appicons.Filled
|
||||||
import ru.n08i40k.polytechnic.next.ui.icons.appicons.filled.Download
|
import ru.n08i40k.polytechnic.next.ui.icons.appicons.filled.Download
|
||||||
@@ -289,7 +288,7 @@ fun MainScreen(
|
|||||||
viewModel(
|
viewModel(
|
||||||
factory = RemoteConfigViewModel.provideFactory(
|
factory = RemoteConfigViewModel.provideFactory(
|
||||||
appContext = LocalContext.current,
|
appContext = LocalContext.current,
|
||||||
remoteConfig = (LocalContext.current as MainActivity).remoteConfig
|
remoteConfig = (LocalContext.current.applicationContext as PolytechnicApplication).container.remoteConfig
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -66,6 +68,10 @@ fun DayCard(
|
|||||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||||
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||||
)
|
)
|
||||||
|
val examCardColors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onErrorContainer,
|
||||||
|
)
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
@@ -93,18 +99,29 @@ fun DayCard(
|
|||||||
text = day.name,
|
text = day.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (day.street != null) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
fontWeight = FontWeight.ExtraLight,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
text = day.street,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (distance >= -1 && distance <= 1) {
|
if (distance >= -1 && distance <= 1) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
text = stringResource(when (distance) {
|
text = stringResource(
|
||||||
|
when (distance) {
|
||||||
-1 -> R.string.yesterday
|
-1 -> R.string.yesterday
|
||||||
0 -> R.string.today
|
0 -> R.string.today
|
||||||
1 -> R.string.tomorrow
|
1 -> R.string.tomorrow
|
||||||
else -> throw RuntimeException()
|
else -> throw RuntimeException()
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +129,9 @@ fun DayCard(
|
|||||||
.collectAsStateWithLifecycle(0)
|
.collectAsStateWithLifecycle(0)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
verticalArrangement = Arrangement.spacedBy(0.5.dp)
|
verticalArrangement = Arrangement.spacedBy(0.5.dp)
|
||||||
) {
|
) {
|
||||||
if (day.lessons.isEmpty()) {
|
if (day.lessons.isEmpty()) {
|
||||||
@@ -125,8 +144,12 @@ fun DayCard(
|
|||||||
|
|
||||||
val cardColors = when (lesson.type) {
|
val cardColors = when (lesson.type) {
|
||||||
LessonType.DEFAULT -> defaultCardColors
|
LessonType.DEFAULT -> defaultCardColors
|
||||||
LessonType.ADDITIONAL -> customCardColors
|
LessonType.ADDITIONAL -> noneCardColors
|
||||||
LessonType.BREAK -> noneCardColors
|
LessonType.BREAK -> noneCardColors
|
||||||
|
LessonType.CONSULTATION -> customCardColors
|
||||||
|
LessonType.INDEPENDENT_WORK -> customCardColors
|
||||||
|
LessonType.EXAM -> examCardColors
|
||||||
|
LessonType.EXAM_WITH_GRADE -> examCardColors
|
||||||
}
|
}
|
||||||
|
|
||||||
val mutableExpanded = remember { mutableStateOf(false) }
|
val mutableExpanded = remember { mutableStateOf(false) }
|
||||||
@@ -139,14 +162,15 @@ fun DayCard(
|
|||||||
val now = lessonIdx == currentLessonIdx
|
val now = lessonIdx == currentLessonIdx
|
||||||
|
|
||||||
if (lesson.type === LessonType.BREAK)
|
if (lesson.type === LessonType.BREAK)
|
||||||
FreeLessonRow(lesson, lesson, cardColors, now)
|
FreeLessonRow(lesson, cardColors, now)
|
||||||
else
|
else
|
||||||
LessonRow(day, lesson, cardColors, now)
|
LessonRow(lesson, cardColors, now)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mutableExpanded.value)
|
if (mutableExpanded.value)
|
||||||
LessonExtraInfo(lesson, mutableExpanded)
|
LessonExtraInfo(lesson, mutableExpanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ fun DayPager(groupOrTeacher: GroupOrTeacher = FakeScheduleRepository.exampleGrou
|
|||||||
}
|
}
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
contentPadding = PaddingValues(horizontal = 20.dp),
|
contentPadding = PaddingValues(horizontal = 7.dp),
|
||||||
verticalAlignment = Alignment.Top,
|
verticalAlignment = Alignment.Top,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(600.dp)
|
.height(600.dp)
|
||||||
|
|||||||
@@ -27,14 +27,10 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import kotlinx.datetime.LocalDateTime
|
|
||||||
import ru.n08i40k.polytechnic.next.R
|
import ru.n08i40k.polytechnic.next.R
|
||||||
import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleRepository
|
import ru.n08i40k.polytechnic.next.data.schedule.impl.FakeScheduleRepository
|
||||||
import ru.n08i40k.polytechnic.next.model.Day
|
|
||||||
import ru.n08i40k.polytechnic.next.model.Lesson
|
import ru.n08i40k.polytechnic.next.model.Lesson
|
||||||
import ru.n08i40k.polytechnic.next.model.LessonTime
|
|
||||||
import ru.n08i40k.polytechnic.next.model.LessonType
|
import ru.n08i40k.polytechnic.next.model.LessonType
|
||||||
import ru.n08i40k.polytechnic.next.model.SubGroup
|
|
||||||
import ru.n08i40k.polytechnic.next.utils.dayMinutes
|
import ru.n08i40k.polytechnic.next.utils.dayMinutes
|
||||||
import ru.n08i40k.polytechnic.next.utils.fmtAsClock
|
import ru.n08i40k.polytechnic.next.utils.fmtAsClock
|
||||||
|
|
||||||
@@ -109,15 +105,8 @@ fun LessonExtraInfo(
|
|||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
private fun LessonViewRow(
|
private fun LessonViewRow(
|
||||||
range: List<Int>? = listOf(1, 3),
|
lesson: Lesson = FakeScheduleRepository.exampleGroup.days[0].lessons[4],
|
||||||
time: LessonTime = LessonTime.fromLocalDateTime(
|
|
||||||
LocalDateTime(2024, 1, 1, 0, 0),
|
|
||||||
LocalDateTime(2024, 1, 1, 1, 0),
|
|
||||||
),
|
|
||||||
timeFormat: LessonTimeFormat = LessonTimeFormat.FROM_TO,
|
timeFormat: LessonTimeFormat = LessonTimeFormat.FROM_TO,
|
||||||
name: String = "Test",
|
|
||||||
subGroups: List<SubGroup> = listOf(),
|
|
||||||
group: String? = "ИС-214/23",
|
|
||||||
cardColors: CardColors = CardDefaults.cardColors(),
|
cardColors: CardColors = CardDefaults.cardColors(),
|
||||||
verticalPadding: Dp = 10.dp,
|
verticalPadding: Dp = 10.dp,
|
||||||
now: Boolean = true,
|
now: Boolean = true,
|
||||||
@@ -126,7 +115,9 @@ private fun LessonViewRow(
|
|||||||
if (timeFormat == LessonTimeFormat.FROM_TO) cardColors.contentColor
|
if (timeFormat == LessonTimeFormat.FROM_TO) cardColors.contentColor
|
||||||
else cardColors.disabledContentColor
|
else cardColors.disabledContentColor
|
||||||
|
|
||||||
val rangeSize = if (range == null) 1 else (range[1] - range[0] + 1) * 2
|
val rangeSize =
|
||||||
|
if (lesson.defaultRange == null) 1
|
||||||
|
else (lesson.defaultRange[1] - lesson.defaultRange[0] + 1) * 2
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
if (now) Modifier.border(
|
if (now) Modifier.border(
|
||||||
@@ -146,17 +137,18 @@ private fun LessonViewRow(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
val rangeString = run {
|
val rangeString = run {
|
||||||
if (range == null)
|
if (lesson.defaultRange == null)
|
||||||
" "
|
" "
|
||||||
else
|
else
|
||||||
buildString {
|
buildString {
|
||||||
val same = range[0] == range[1]
|
val same = lesson.defaultRange[0] == lesson.defaultRange[1]
|
||||||
|
|
||||||
append(if (same) " " else range[0])
|
append(if (same) " " else lesson.defaultRange[0])
|
||||||
append(if (same) range[0] else "-")
|
append(if (same) lesson.defaultRange[0] else "-")
|
||||||
append(if (same) " " else range[1])
|
append(if (same) " " else lesson.defaultRange[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 1-2
|
||||||
Text(
|
Text(
|
||||||
text = rangeString,
|
text = rangeString,
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
@@ -170,8 +162,9 @@ private fun LessonViewRow(
|
|||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
val formattedTime: ArrayList<String> =
|
val formattedTime: ArrayList<String> =
|
||||||
fmtTime(time.start.dayMinutes, time.end.dayMinutes, timeFormat)
|
fmtTime(lesson.time.start.dayMinutes, lesson.time.end.dayMinutes, timeFormat)
|
||||||
|
|
||||||
|
// 10:20 - 11:40
|
||||||
Text(
|
Text(
|
||||||
text = formattedTime[0],
|
text = formattedTime[0],
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
@@ -194,17 +187,32 @@ private fun LessonViewRow(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
if (lesson.type.value > LessonType.BREAK.value) {
|
||||||
Text(
|
Text(
|
||||||
text = name,
|
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)
|
||||||
|
else -> throw Error("Unknown lesson type!")
|
||||||
|
},
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
color = contentColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = lesson.name ?: stringResource(R.string.lesson_break),
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = contentColor
|
color = contentColor
|
||||||
)
|
)
|
||||||
|
|
||||||
if (group != null) {
|
if (lesson.group != null) {
|
||||||
Text(
|
Text(
|
||||||
text = group,
|
text = lesson.group,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
@@ -212,9 +220,10 @@ private fun LessonViewRow(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (subGroup in subGroups) {
|
for (subGroup in lesson.subGroups) {
|
||||||
Text(
|
Text(
|
||||||
text = subGroup.teacher,
|
text = subGroup.teacher,
|
||||||
|
fontWeight = FontWeight.Thin,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = contentColor
|
color = contentColor
|
||||||
@@ -223,14 +232,17 @@ private fun LessonViewRow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier = Modifier.wrapContentWidth()) {
|
Column(modifier = Modifier.wrapContentWidth()) {
|
||||||
if (subGroups.size != 1) {
|
if (lesson.subGroups.size != 1) {
|
||||||
for (i in 0..<(if (group != null) 2 else 1))
|
Text(text = "")
|
||||||
|
|
||||||
|
if (lesson.group != null)
|
||||||
Text(text = "")
|
Text(text = "")
|
||||||
}
|
}
|
||||||
for (subGroup in subGroups) {
|
for (subGroup in lesson.subGroups) {
|
||||||
Text(
|
Text(
|
||||||
text = subGroup.cabinet,
|
text = subGroup.cabinet,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
|
fontWeight = FontWeight.Thin,
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
color = contentColor
|
color = contentColor
|
||||||
)
|
)
|
||||||
@@ -247,17 +259,12 @@ private fun LessonViewRow(
|
|||||||
@Composable
|
@Composable
|
||||||
fun FreeLessonRow(
|
fun FreeLessonRow(
|
||||||
lesson: Lesson = FakeScheduleRepository.exampleGroup.days[0].lessons[0],
|
lesson: Lesson = FakeScheduleRepository.exampleGroup.days[0].lessons[0],
|
||||||
nextLesson: Lesson = FakeScheduleRepository.exampleGroup.days[0].lessons[1],
|
|
||||||
cardColors: CardColors = CardDefaults.cardColors(),
|
cardColors: CardColors = CardDefaults.cardColors(),
|
||||||
now: Boolean = true
|
now: Boolean = true
|
||||||
) {
|
) {
|
||||||
LessonViewRow(
|
LessonViewRow(
|
||||||
lesson.defaultRange,
|
lesson,
|
||||||
LessonTime(lesson.time.start, nextLesson.time.end),
|
|
||||||
LessonTimeFormat.ONLY_MINUTES_DURATION,
|
LessonTimeFormat.ONLY_MINUTES_DURATION,
|
||||||
stringResource(R.string.lesson_break),
|
|
||||||
lesson.subGroups,
|
|
||||||
lesson.group,
|
|
||||||
cardColors,
|
cardColors,
|
||||||
2.5.dp,
|
2.5.dp,
|
||||||
now
|
now
|
||||||
@@ -267,18 +274,13 @@ fun FreeLessonRow(
|
|||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
fun LessonRow(
|
fun LessonRow(
|
||||||
day: Day = FakeScheduleRepository.exampleGroup.days[0],
|
|
||||||
lesson: Lesson = FakeScheduleRepository.exampleGroup.days[0].lessons[0],
|
lesson: Lesson = FakeScheduleRepository.exampleGroup.days[0].lessons[0],
|
||||||
cardColors: CardColors = CardDefaults.cardColors(),
|
cardColors: CardColors = CardDefaults.cardColors(),
|
||||||
now: Boolean = true,
|
now: Boolean = true,
|
||||||
) {
|
) {
|
||||||
LessonViewRow(
|
LessonViewRow(
|
||||||
lesson.defaultRange,
|
lesson,
|
||||||
lesson.time,
|
|
||||||
LessonTimeFormat.FROM_TO,
|
LessonTimeFormat.FROM_TO,
|
||||||
lesson.name!!,
|
|
||||||
lesson.subGroups,
|
|
||||||
lesson.group,
|
|
||||||
cardColors,
|
cardColors,
|
||||||
5.dp,
|
5.dp,
|
||||||
now
|
now
|
||||||
|
|||||||
@@ -80,4 +80,8 @@
|
|||||||
<string name="teacher_name">ФИО преподавателя</string>
|
<string name="teacher_name">ФИО преподавателя</string>
|
||||||
<string name="teacher_not_selected">Преподаватель не выбран или вы допустили ошибку в его ФИО.</string>
|
<string name="teacher_not_selected">Преподаватель не выбран или вы допустили ошибку в его ФИО.</string>
|
||||||
<string name="failed_to_fetch_teacher_names">Не удалось получить список ФИО преподавателей!</string>
|
<string name="failed_to_fetch_teacher_names">Не удалось получить список ФИО преподавателей!</string>
|
||||||
|
<string name="lesson_type_consultation">Консультация</string>
|
||||||
|
<string name="lesson_type_independent_work">Самостоятельная работа</string>
|
||||||
|
<string name="lesson_type_exam">ЗАЧЁТ</string>
|
||||||
|
<string name="lesson_type_exam_with_grade">ЗАЧЁТ С ОЦЕНКОЙ</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -80,4 +80,8 @@
|
|||||||
<string name="teacher_name">Teacher name</string>
|
<string name="teacher_name">Teacher name</string>
|
||||||
<string name="teacher_not_selected">Teacher not selected or you made mistake in his name.</string>
|
<string name="teacher_not_selected">Teacher not selected or you made mistake in his name.</string>
|
||||||
<string name="failed_to_fetch_teacher_names">Failed to fetch teacher names!</string>
|
<string name="failed_to_fetch_teacher_names">Failed to fetch teacher names!</string>
|
||||||
|
<string name="lesson_type_consultation">Consultation</string>
|
||||||
|
<string name="lesson_type_independent_work">Independent work</string>
|
||||||
|
<string name="lesson_type_exam">EXAM</string>
|
||||||
|
<string name="lesson_type_exam_with_grade">EXAM WITH GRADE</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,27 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<defaults>
|
<defaults>
|
||||||
|
<entry>
|
||||||
|
<key>serverVersion</key>
|
||||||
|
<value>2.2.2</value>
|
||||||
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<key>linkUpdateDelay</key>
|
<key>linkUpdateDelay</key>
|
||||||
<value>15</value>
|
<value>15</value>
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<key>minVersion</key>
|
<key>minVersion</key>
|
||||||
<value>1.3.0</value>
|
<value>2.0.1</value>
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<key>currVersion</key>
|
|
||||||
<value>1.5.0</value>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<key>downloadLink</key>
|
|
||||||
<value>https://t.me/polytechnic_next/16</value>
|
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<key>telegramLink</key>
|
<key>telegramLink</key>
|
||||||
<value>https://t.me/polytechnic_next</value>
|
<value>https://t.me/polytechnic_next</value>
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<key>serverVersion</key>
|
<key>linkParserRegex</key>
|
||||||
<value>1.3.0</value>
|
<value><a href="(/\d{4}/[.\w\-_]+\.xls)"></value>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>downloadLink</key>
|
||||||
|
<value>https://t.me/polytechnic_next/68</value>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>currVersion</key>
|
||||||
|
<value>2.2.1</value>
|
||||||
</entry>
|
</entry>
|
||||||
</defaults>
|
</defaults>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
[versions]
|
[versions]
|
||||||
accompanistSwiperefresh = "0.36.0"
|
accompanistSwiperefresh = "0.36.0"
|
||||||
agp = "8.7.2"
|
agp = "8.7.3"
|
||||||
firebaseBom = "33.5.1"
|
firebaseBom = "33.7.0"
|
||||||
hiltAndroid = "2.52"
|
hiltAndroid = "2.53.1"
|
||||||
hiltAndroidCompiler = "2.52"
|
hiltAndroidCompiler = "2.53.1"
|
||||||
hiltNavigationCompose = "1.2.0"
|
hiltNavigationCompose = "1.2.0"
|
||||||
kotlin = "2.0.10"
|
kotlin = "2.0.10"
|
||||||
coreKtx = "1.15.0"
|
coreKtx = "1.15.0"
|
||||||
@@ -13,12 +13,12 @@ espressoCore = "3.6.1"
|
|||||||
kotlinxSerializationJson = "1.7.3"
|
kotlinxSerializationJson = "1.7.3"
|
||||||
lifecycleRuntimeKtx = "2.8.7"
|
lifecycleRuntimeKtx = "2.8.7"
|
||||||
activityCompose = "1.9.3"
|
activityCompose = "1.9.3"
|
||||||
composeBom = "2024.10.01"
|
composeBom = "2024.12.01"
|
||||||
mockitoKotlin = "5.4.0"
|
mockitoKotlin = "5.4.0"
|
||||||
protobufLite = "3.0.1"
|
protobufLite = "3.0.1"
|
||||||
volley = "1.2.1"
|
volley = "1.2.1"
|
||||||
datastore = "1.1.1"
|
datastore = "1.1.1"
|
||||||
navigationCompose = "2.8.3"
|
navigationCompose = "2.8.5"
|
||||||
googleFirebaseCrashlytics = "3.0.2"
|
googleFirebaseCrashlytics = "3.0.2"
|
||||||
workRuntime = "2.10.0"
|
workRuntime = "2.10.0"
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ androidx-ui = { group = "androidx.compose.ui", name = "ui" }
|
|||||||
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||||
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||||
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version = "1.7.5" }
|
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version = "1.7.6" }
|
||||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||||
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version = "0.6.1" }
|
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version = "0.6.1" }
|
||||||
@@ -52,8 +52,8 @@ volley = { group = "com.android.volley", name = "volley", version.ref = "volley"
|
|||||||
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
|
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
|
||||||
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
|
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
|
||||||
firebase-analytics = { module = "com.google.firebase:firebase-analytics", version = "22.1.2" }
|
firebase-analytics = { module = "com.google.firebase:firebase-analytics", version = "22.1.2" }
|
||||||
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics", version = "19.2.1" }
|
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics", version = "19.3.0" }
|
||||||
firebase-messaging = { group = "com.google.firebase", name = "firebase-messaging", version = "24.0.3" }
|
firebase-messaging = { group = "com.google.firebase", name = "firebase-messaging", version = "24.1.0" }
|
||||||
firebase-config = { group = "com.google.firebase", name = "firebase-config", version = "22.0.1" }
|
firebase-config = { group = "com.google.firebase", name = "firebase-config", version = "22.0.1" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|||||||
Reference in New Issue
Block a user