mirror of
https://github.com/n08i40k/polytechnic-android.git
synced 2025-12-06 09:47:48 +03:00
1.3.1
Дополнительная информация о последних обновлениях.
This commit is contained in:
9
.idea/appInsightsSettings.xml
generated
9
.idea/appInsightsSettings.xml
generated
@@ -17,6 +17,15 @@
|
|||||||
</option>
|
</option>
|
||||||
<option name="signal" value="SIGNAL_UNSPECIFIED" />
|
<option name="signal" value="SIGNAL_UNSPECIFIED" />
|
||||||
<option name="timeIntervalDays" value="THIRTY_DAYS" />
|
<option name="timeIntervalDays" value="THIRTY_DAYS" />
|
||||||
|
<option name="versions">
|
||||||
|
<list>
|
||||||
|
<VersionSetting>
|
||||||
|
<option name="buildVersion" value="3" />
|
||||||
|
<option name="displayName" value="1.2 (3)" />
|
||||||
|
<option name="displayVersion" value="1.2" />
|
||||||
|
</VersionSetting>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
<option name="visibilityType" value="ALL" />
|
<option name="visibilityType" value="ALL" />
|
||||||
</InsightsFilterSettings>
|
</InsightsFilterSettings>
|
||||||
</value>
|
</value>
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ android {
|
|||||||
applicationId = "ru.n08i40k.polytechnic.next"
|
applicationId = "ru.n08i40k.polytechnic.next"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 6
|
versionCode = 7
|
||||||
versionName = "1.3.0"
|
versionName = "1.3.1"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.n08i40k.polytechnic.next.data.cache
|
package ru.n08i40k.polytechnic.next.data.cache
|
||||||
|
|
||||||
import ru.n08i40k.polytechnic.next.CachedResponse
|
import ru.n08i40k.polytechnic.next.CachedResponse
|
||||||
|
import ru.n08i40k.polytechnic.next.UpdateDates
|
||||||
|
|
||||||
interface NetworkCacheRepository {
|
interface NetworkCacheRepository {
|
||||||
suspend fun put(url: String, data: String)
|
suspend fun put(url: String, data: String)
|
||||||
@@ -12,4 +13,8 @@ interface NetworkCacheRepository {
|
|||||||
suspend fun isHashPresent(): Boolean
|
suspend fun isHashPresent(): Boolean
|
||||||
|
|
||||||
suspend fun setHash(hash: String)
|
suspend fun setHash(hash: String)
|
||||||
|
|
||||||
|
suspend fun getUpdateDates(): UpdateDates
|
||||||
|
|
||||||
|
suspend fun setUpdateDates(cache: Long, schedule: Long)
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.n08i40k.polytechnic.next.data.cache.impl
|
package ru.n08i40k.polytechnic.next.data.cache.impl
|
||||||
|
|
||||||
import ru.n08i40k.polytechnic.next.CachedResponse
|
import ru.n08i40k.polytechnic.next.CachedResponse
|
||||||
|
import ru.n08i40k.polytechnic.next.UpdateDates
|
||||||
import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
||||||
|
|
||||||
class FakeNetworkCacheRepository : NetworkCacheRepository {
|
class FakeNetworkCacheRepository : NetworkCacheRepository {
|
||||||
@@ -17,4 +18,10 @@ class FakeNetworkCacheRepository : NetworkCacheRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setHash(hash: String) {}
|
override suspend fun setHash(hash: String) {}
|
||||||
|
|
||||||
|
override suspend fun getUpdateDates(): UpdateDates {
|
||||||
|
return UpdateDates.newBuilder().build()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setUpdateDates(cache: Long, schedule: Long) {}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import ru.n08i40k.polytechnic.next.CachedResponse
|
import ru.n08i40k.polytechnic.next.CachedResponse
|
||||||
|
import ru.n08i40k.polytechnic.next.UpdateDates
|
||||||
import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
||||||
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
|
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -14,6 +15,7 @@ import javax.inject.Inject
|
|||||||
class LocalNetworkCacheRepository
|
class LocalNetworkCacheRepository
|
||||||
@Inject constructor(private val applicationContext: Context) : NetworkCacheRepository {
|
@Inject constructor(private val applicationContext: Context) : NetworkCacheRepository {
|
||||||
private val cacheMap: MutableMap<String, CachedResponse> = mutableMapOf()
|
private val cacheMap: MutableMap<String, CachedResponse> = mutableMapOf()
|
||||||
|
private var updateDates: UpdateDates = UpdateDates.newBuilder().build()
|
||||||
private var hash: String? = null
|
private var hash: String? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -75,18 +77,38 @@ class LocalNetworkCacheRepository
|
|||||||
this.cacheMap
|
this.cacheMap
|
||||||
.mapNotNull { if (it.value.hash != this.hash) it.key else null }
|
.mapNotNull { if (it.value.hash != this.hash) it.key else null }
|
||||||
.forEach { this.cacheMap.remove(it) }
|
.forEach { this.cacheMap.remove(it) }
|
||||||
|
save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getUpdateDates(): UpdateDates {
|
||||||
|
return this.updateDates
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setUpdateDates(cache: Long, schedule: Long) {
|
||||||
|
updateDates = UpdateDates
|
||||||
|
.newBuilder()
|
||||||
|
.setCache(cache)
|
||||||
|
.setSchedule(schedule).build()
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
applicationContext.settingsDataStore.updateData {
|
||||||
|
it
|
||||||
|
.toBuilder()
|
||||||
|
.setUpdateDates(updateDates)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun save() {
|
private suspend fun save() {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
runBlocking {
|
applicationContext.settingsDataStore.updateData {
|
||||||
applicationContext.settingsDataStore.updateData {
|
it
|
||||||
it
|
.toBuilder()
|
||||||
.toBuilder()
|
.putAllCacheStorage(cacheMap)
|
||||||
.putAllCacheStorage(cacheMap)
|
.build()
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ open class RequestBase(
|
|||||||
override fun getHeaders(): MutableMap<String, String> {
|
override fun getHeaders(): MutableMap<String, String> {
|
||||||
val headers = mutableMapOf<String, String>()
|
val headers = mutableMapOf<String, String>()
|
||||||
headers["Content-Type"] = "application/json; charset=utf-8"
|
headers["Content-Type"] = "application/json; charset=utf-8"
|
||||||
|
headers["version"] = "1"
|
||||||
|
|
||||||
return headers
|
return headers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,10 @@ open class CachedRequest(
|
|||||||
|
|
||||||
if (!response.cacheUpdateRequired) {
|
if (!response.cacheUpdateRequired) {
|
||||||
logger.info("Cache update was not required!")
|
logger.info("Cache update was not required!")
|
||||||
runBlocking { repository.setHash(response.cacheHash) }
|
runBlocking {
|
||||||
|
repository.setUpdateDates(response.lastCacheUpdate, response.lastScheduleUpdate)
|
||||||
|
repository.setHash(response.cacheHash)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info("Cache update was required!")
|
logger.info("Cache update was required!")
|
||||||
val updateResult = runBlocking { updateMainPage() }
|
val updateResult = runBlocking { updateMainPage() }
|
||||||
@@ -105,7 +108,13 @@ open class CachedRequest(
|
|||||||
when (updateResult) {
|
when (updateResult) {
|
||||||
is MyResult.Success -> {
|
is MyResult.Success -> {
|
||||||
logger.info("Cache update was successful!")
|
logger.info("Cache update was successful!")
|
||||||
runBlocking { repository.setHash(updateResult.data.cacheHash) }
|
runBlocking {
|
||||||
|
repository.setUpdateDates(
|
||||||
|
updateResult.data.lastCacheUpdate,
|
||||||
|
updateResult.data.lastScheduleUpdate
|
||||||
|
)
|
||||||
|
repository.setHash(updateResult.data.cacheHash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is MyResult.Failure -> {
|
is MyResult.Failure -> {
|
||||||
|
|||||||
@@ -6,4 +6,6 @@ import kotlinx.serialization.Serializable
|
|||||||
data class ScheduleGetCacheStatusResponse(
|
data class ScheduleGetCacheStatusResponse(
|
||||||
val cacheUpdateRequired: Boolean,
|
val cacheUpdateRequired: Boolean,
|
||||||
val cacheHash: String,
|
val cacheHash: String,
|
||||||
|
val lastCacheUpdate: Long,
|
||||||
|
val lastScheduleUpdate: Long,
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package ru.n08i40k.polytechnic.next.ui
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.core.MutableTransitionState
|
||||||
|
import androidx.compose.animation.core.Transition
|
||||||
|
import androidx.compose.animation.core.animateFloat
|
||||||
|
import androidx.compose.animation.core.rememberTransition
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.animation.expandVertically
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.shrinkVertically
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
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
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ExpandableCard(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
expanded: Boolean,
|
||||||
|
onExpandedChange: () -> Unit,
|
||||||
|
title: String,
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
val transitionState = remember {
|
||||||
|
MutableTransitionState(expanded).apply {
|
||||||
|
targetState = !expanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val transition = rememberTransition(transitionState)
|
||||||
|
|
||||||
|
Card(modifier = modifier.clickable {
|
||||||
|
onExpandedChange()
|
||||||
|
transitionState.targetState = expanded
|
||||||
|
}) {
|
||||||
|
Column {
|
||||||
|
ExpandableCardHeader(title, transition)
|
||||||
|
ExpandableCardContent(visible = expanded, content = content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ExpandableCardContent(
|
||||||
|
visible: Boolean = true,
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
val enterTransition = remember {
|
||||||
|
expandVertically(
|
||||||
|
expandFrom = Alignment.Top,
|
||||||
|
animationSpec = tween(durationMillis = 250)
|
||||||
|
) + fadeIn(animationSpec = tween(durationMillis = 250, delayMillis = 250))
|
||||||
|
}
|
||||||
|
|
||||||
|
val exitTransition = remember {
|
||||||
|
fadeOut(
|
||||||
|
animationSpec = tween(durationMillis = 250)
|
||||||
|
) + shrinkVertically(
|
||||||
|
shrinkTowards = Alignment.Top,
|
||||||
|
animationSpec = tween(durationMillis = 250, delayMillis = 250)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = visible,
|
||||||
|
enter = enterTransition,
|
||||||
|
exit = exitTransition
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ExpandableCardTitle(text: String) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(0.dp, 10.dp),
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ExpandableCardArrow(
|
||||||
|
transition: Transition<Boolean>
|
||||||
|
) {
|
||||||
|
val rotationDegree by transition.animateFloat(
|
||||||
|
{ tween(durationMillis = 250) },
|
||||||
|
label = "Arrow Rotation"
|
||||||
|
) {
|
||||||
|
if (it) 360F else 180F
|
||||||
|
}
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.rotate(rotationDegree),
|
||||||
|
imageVector = Icons.Filled.ArrowDropDown,
|
||||||
|
contentDescription = "Expandable Arrow"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ExpandableCardHeader(
|
||||||
|
title: String = "TODO",
|
||||||
|
transition: Transition<Boolean>
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(10.dp, 0.dp),
|
||||||
|
contentAlignment = Alignment.CenterEnd,
|
||||||
|
) {
|
||||||
|
ExpandableCardArrow(transition)
|
||||||
|
ExpandableCardTitle(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
package ru.n08i40k.polytechnic.next.ui.main.schedule
|
package ru.n08i40k.polytechnic.next.ui.main.schedule
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -10,7 +16,10 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import ru.n08i40k.polytechnic.next.MainViewModel
|
||||||
import ru.n08i40k.polytechnic.next.R
|
import ru.n08i40k.polytechnic.next.R
|
||||||
import ru.n08i40k.polytechnic.next.data.MockAppContainer
|
import ru.n08i40k.polytechnic.next.data.MockAppContainer
|
||||||
import ru.n08i40k.polytechnic.next.ui.LoadingContent
|
import ru.n08i40k.polytechnic.next.ui.LoadingContent
|
||||||
@@ -26,16 +35,26 @@ fun ScheduleScreen(
|
|||||||
val uiState by scheduleViewModel.uiState.collectAsStateWithLifecycle()
|
val uiState by scheduleViewModel.uiState.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
LoadingContent(
|
LoadingContent(
|
||||||
empty = when (uiState) {
|
empty = uiState.isLoading,
|
||||||
is ScheduleUiState.NoSchedule -> uiState.isLoading
|
|
||||||
is ScheduleUiState.HasSchedule -> false
|
|
||||||
},
|
|
||||||
loading = uiState.isLoading,
|
loading = uiState.isLoading,
|
||||||
onRefresh = onRefreshSchedule
|
onRefresh = { onRefreshSchedule() },
|
||||||
|
verticalArrangement = Arrangement.Top
|
||||||
) {
|
) {
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is ScheduleUiState.HasSchedule -> {
|
is ScheduleUiState.HasSchedule -> {
|
||||||
DayPager((uiState as ScheduleUiState.HasSchedule).group)
|
Box {
|
||||||
|
val networkCacheRepository =
|
||||||
|
hiltViewModel<MainViewModel>(LocalContext.current as ComponentActivity)
|
||||||
|
.appContainer
|
||||||
|
.networkCacheRepository
|
||||||
|
|
||||||
|
UpdateInfo(networkCacheRepository)
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Spacer(modifier = Modifier.height(200.dp))
|
||||||
|
DayPager((uiState as ScheduleUiState.HasSchedule).group)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ScheduleUiState.NoSchedule -> {
|
is ScheduleUiState.NoSchedule -> {
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package ru.n08i40k.polytechnic.next.ui.main.schedule
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
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.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.Saver
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import ru.n08i40k.polytechnic.next.MainViewModel
|
||||||
|
import ru.n08i40k.polytechnic.next.R
|
||||||
|
import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
||||||
|
import ru.n08i40k.polytechnic.next.data.cache.impl.FakeNetworkCacheRepository
|
||||||
|
import ru.n08i40k.polytechnic.next.ui.ExpandableCard
|
||||||
|
import ru.n08i40k.polytechnic.next.ui.model.ScheduleViewModel
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
|
fun Date.toString(format: String, locale: Locale = Locale.getDefault()): String {
|
||||||
|
val formatter = SimpleDateFormat(format, locale)
|
||||||
|
return formatter.format(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentDateTime(): Date {
|
||||||
|
return Calendar.getInstance().time
|
||||||
|
}
|
||||||
|
|
||||||
|
val expanded = mutableStateOf(false)
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
fun UpdateInfo(networkCacheRepository: NetworkCacheRepository = FakeNetworkCacheRepository()) {
|
||||||
|
var expanded by remember { expanded }
|
||||||
|
|
||||||
|
val format = "hh:mm:ss dd.MM.yyyy"
|
||||||
|
|
||||||
|
val updateDates = remember { runBlocking { networkCacheRepository.getUpdateDates() } }
|
||||||
|
|
||||||
|
val currentDate = remember { getCurrentDateTime().toString(format) }
|
||||||
|
val cacheUpdateDate = remember { Date(updateDates.cache).toString(format) }
|
||||||
|
val scheduleUpdateDate = remember { Date(updateDates.schedule).toString(format) }
|
||||||
|
|
||||||
|
ExpandableCard(
|
||||||
|
expanded = expanded,
|
||||||
|
onExpandedChange = { expanded = !expanded },
|
||||||
|
title = stringResource(R.string.update_info_header)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(10.dp)
|
||||||
|
) {
|
||||||
|
Row(horizontalArrangement = Arrangement.Center) {
|
||||||
|
Text(text = stringResource(R.string.last_local_update) + " - ")
|
||||||
|
Text(text = currentDate, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(horizontalArrangement = Arrangement.Center) {
|
||||||
|
Text(text = stringResource(R.string.last_server_cache_update) + " - ")
|
||||||
|
Text(text = cacheUpdateDate, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(horizontalArrangement = Arrangement.Center) {
|
||||||
|
Text(text = stringResource(R.string.last_server_schedule_update) + " - ")
|
||||||
|
Text(text = scheduleUpdateDate, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,15 @@ message CachedResponse {
|
|||||||
string data = 2;
|
string data = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message UpdateDates {
|
||||||
|
int64 cache = 1;
|
||||||
|
int64 schedule = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message Settings {
|
message Settings {
|
||||||
string user_id = 1;
|
string user_id = 1;
|
||||||
string access_token = 2;
|
string access_token = 2;
|
||||||
string group = 3;
|
string group = 3;
|
||||||
map<string, CachedResponse> cache_storage = 4;
|
map<string, CachedResponse> cache_storage = 4;
|
||||||
|
UpdateDates update_dates = 5;
|
||||||
}
|
}
|
||||||
@@ -32,4 +32,8 @@
|
|||||||
<string name="change_group">Сменить группу</string>
|
<string name="change_group">Сменить группу</string>
|
||||||
<string name="sign_out">Выйти с аккаунта</string>
|
<string name="sign_out">Выйти с аккаунта</string>
|
||||||
<string name="cabinets">Кабинеты</string>
|
<string name="cabinets">Кабинеты</string>
|
||||||
|
<string name="last_local_update">Последнее локальное обновление</string>
|
||||||
|
<string name="last_server_cache_update">Последнее обновление кеша</string>
|
||||||
|
<string name="last_server_schedule_update">Последнее обновление расписания</string>
|
||||||
|
<string name="update_info_header">Дополнительная информация</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -32,4 +32,8 @@
|
|||||||
<string name="change_group">Change group</string>
|
<string name="change_group">Change group</string>
|
||||||
<string name="sign_out">Sign out</string>
|
<string name="sign_out">Sign out</string>
|
||||||
<string name="cabinets">Cabinets</string>
|
<string name="cabinets">Cabinets</string>
|
||||||
|
<string name="last_local_update">Last local update</string>
|
||||||
|
<string name="last_server_cache_update">Last server cache update</string>
|
||||||
|
<string name="last_server_schedule_update">Last server schedule update</string>
|
||||||
|
<string name="update_info_header">Additional information</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user