mirror of
https://github.com/n08i40k/polytechnic-android.git
synced 2025-12-06 09:47:48 +03:00
1.3.2
Фикс краша при получении расписания с включённым VPN. Допилено обновление расписания без перезагрузки всего экрана.
This commit is contained in:
6
.idea/appInsightsSettings.xml
generated
6
.idea/appInsightsSettings.xml
generated
@@ -20,9 +20,9 @@
|
|||||||
<option name="versions">
|
<option name="versions">
|
||||||
<list>
|
<list>
|
||||||
<VersionSetting>
|
<VersionSetting>
|
||||||
<option name="buildVersion" value="3" />
|
<option name="buildVersion" value="7" />
|
||||||
<option name="displayName" value="1.2 (3)" />
|
<option name="displayName" value="1.3.1 (7)" />
|
||||||
<option name="displayVersion" value="1.2" />
|
<option name="displayVersion" value="1.3.1" />
|
||||||
</VersionSetting>
|
</VersionSetting>
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
124
.idea/codeStyles/Project.xml
generated
Normal file
124
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
|
<JetCodeStyleSettings>
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</JetCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="XML">
|
||||||
|
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
<arrangement>
|
||||||
|
<rules>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:android</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>style</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
</rules>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="kotlin">
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -7,7 +7,7 @@
|
|||||||
</list>
|
</list>
|
||||||
</component>
|
</component>
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ android {
|
|||||||
applicationId = "ru.n08i40k.polytechnic.next"
|
applicationId = "ru.n08i40k.polytechnic.next"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 7
|
versionCode = 8
|
||||||
versionName = "1.3.1"
|
versionName = "1.3.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package ru.n08i40k.polytechnic.next.data
|
package ru.n08i40k.polytechnic.next.data
|
||||||
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
sealed interface MyResult<out R> {
|
sealed interface MyResult<out R> {
|
||||||
data class Success<out T>(val data: T) : MyResult<T>
|
data class Success<out T>(val data: T) : MyResult<T>
|
||||||
data class Failure(val exception: Exception) : MyResult<Nothing>
|
data class Failure(val exception: Exception) : MyResult<Nothing>
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ class LocalNetworkCacheRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun get(url: String): CachedResponse? {
|
override suspend fun get(url: String): CachedResponse? {
|
||||||
if (this.hash == null)
|
// Если кешированого ответа нет, то возвращаем null
|
||||||
return null
|
// Если хеши не совпадают и локальный хеш присутствует, то возвращаем null
|
||||||
|
|
||||||
val response = cacheMap[url]
|
val response = cacheMap[url] ?: return null
|
||||||
|
|
||||||
if (response?.hash != this.hash)
|
if (response.hash != this.hash && this.hash != null)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package ru.n08i40k.polytechnic.next.data.schedule
|
package ru.n08i40k.polytechnic.next.data.schedule
|
||||||
|
|
||||||
import ru.n08i40k.polytechnic.next.model.Group
|
|
||||||
import ru.n08i40k.polytechnic.next.data.MyResult
|
import ru.n08i40k.polytechnic.next.data.MyResult
|
||||||
|
import ru.n08i40k.polytechnic.next.model.Group
|
||||||
|
|
||||||
interface ScheduleRepository {
|
interface ScheduleRepository {
|
||||||
suspend fun getGroup(): MyResult<Group>
|
suspend fun getGroup(): MyResult<Group>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import ru.n08i40k.polytechnic.next.data.MyResult
|
||||||
|
import ru.n08i40k.polytechnic.next.data.schedule.ScheduleRepository
|
||||||
import ru.n08i40k.polytechnic.next.model.Day
|
import ru.n08i40k.polytechnic.next.model.Day
|
||||||
import ru.n08i40k.polytechnic.next.model.Group
|
import ru.n08i40k.polytechnic.next.model.Group
|
||||||
import ru.n08i40k.polytechnic.next.data.schedule.ScheduleRepository
|
|
||||||
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.LessonTime
|
||||||
import ru.n08i40k.polytechnic.next.model.LessonType
|
import ru.n08i40k.polytechnic.next.model.LessonType
|
||||||
import ru.n08i40k.polytechnic.next.data.MyResult
|
|
||||||
|
|
||||||
class FakeScheduleRepository : ScheduleRepository {
|
class FakeScheduleRepository : ScheduleRepository {
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ru.n08i40k.polytechnic.next.data.schedule.impl
|
package ru.n08i40k.polytechnic.next.data.schedule.impl
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.volley.toolbox.RequestFuture
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@@ -12,7 +11,7 @@ import ru.n08i40k.polytechnic.next.data.schedule.ScheduleRepository
|
|||||||
import ru.n08i40k.polytechnic.next.model.Group
|
import ru.n08i40k.polytechnic.next.model.Group
|
||||||
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetRequest
|
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetRequest
|
||||||
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetRequestData
|
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetRequestData
|
||||||
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetResponse
|
import ru.n08i40k.polytechnic.next.network.tryFuture
|
||||||
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
|
import ru.n08i40k.polytechnic.next.settings.settingsDataStore
|
||||||
|
|
||||||
class RemoteScheduleRepository(private val context: Context) : ScheduleRepository {
|
class RemoteScheduleRepository(private val context: Context) : ScheduleRepository {
|
||||||
@@ -27,18 +26,18 @@ class RemoteScheduleRepository(private val context: Context) : ScheduleRepositor
|
|||||||
if (groupName.isEmpty())
|
if (groupName.isEmpty())
|
||||||
return@withContext MyResult.Failure(IllegalArgumentException("No group name provided!"))
|
return@withContext MyResult.Failure(IllegalArgumentException("No group name provided!"))
|
||||||
|
|
||||||
val future = RequestFuture.newFuture<ScheduleGetResponse>()
|
val response = tryFuture {
|
||||||
ScheduleGetRequest(
|
ScheduleGetRequest(
|
||||||
ScheduleGetRequestData(groupName),
|
ScheduleGetRequestData(groupName),
|
||||||
context,
|
context,
|
||||||
future,
|
it,
|
||||||
future
|
it
|
||||||
).send()
|
)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
when (response) {
|
||||||
MyResult.Success(future.get().group)
|
is MyResult.Failure -> response
|
||||||
} catch (exception: Exception) {
|
is MyResult.Success -> MyResult.Success(response.data.group)
|
||||||
MyResult.Failure(exception)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import ru.n08i40k.polytechnic.next.data.MyResult
|
|||||||
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
|
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
|
||||||
import ru.n08i40k.polytechnic.next.model.Profile
|
import ru.n08i40k.polytechnic.next.model.Profile
|
||||||
import ru.n08i40k.polytechnic.next.model.UserRole
|
import ru.n08i40k.polytechnic.next.model.UserRole
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
class FakeProfileRepository : ProfileRepository {
|
class FakeProfileRepository : ProfileRepository {
|
||||||
private var counter = 0
|
private var counter = 0
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
package ru.n08i40k.polytechnic.next.data.users.impl
|
package ru.n08i40k.polytechnic.next.data.users.impl
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.volley.toolbox.RequestFuture
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import ru.n08i40k.polytechnic.next.data.MyResult
|
import ru.n08i40k.polytechnic.next.data.MyResult
|
||||||
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
|
import ru.n08i40k.polytechnic.next.data.users.ProfileRepository
|
||||||
import ru.n08i40k.polytechnic.next.model.Profile
|
import ru.n08i40k.polytechnic.next.model.Profile
|
||||||
import ru.n08i40k.polytechnic.next.network.data.profile.UsersMeRequest
|
import ru.n08i40k.polytechnic.next.network.data.profile.UsersMeRequest
|
||||||
|
import ru.n08i40k.polytechnic.next.network.tryFuture
|
||||||
|
|
||||||
class RemoteProfileRepository(private val context: Context) : ProfileRepository {
|
class RemoteProfileRepository(private val context: Context) : ProfileRepository {
|
||||||
override suspend fun getProfile(): MyResult<Profile> {
|
override suspend fun getProfile(): MyResult<Profile> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
val responseFuture = RequestFuture.newFuture<Profile>()
|
tryFuture {
|
||||||
UsersMeRequest(
|
UsersMeRequest(
|
||||||
context,
|
context,
|
||||||
responseFuture,
|
it,
|
||||||
responseFuture
|
it
|
||||||
).send()
|
)
|
||||||
|
|
||||||
try {
|
|
||||||
MyResult.Success(responseFuture.get())
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
MyResult.Failure(exception)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,15 @@ import android.content.Context
|
|||||||
import com.android.volley.Request
|
import com.android.volley.Request
|
||||||
import com.android.volley.RequestQueue
|
import com.android.volley.RequestQueue
|
||||||
import com.android.volley.Response
|
import com.android.volley.Response
|
||||||
|
import com.android.volley.VolleyError
|
||||||
import com.android.volley.toolbox.HurlStack
|
import com.android.volley.toolbox.HurlStack
|
||||||
|
import com.android.volley.toolbox.RequestFuture
|
||||||
import com.android.volley.toolbox.StringRequest
|
import com.android.volley.toolbox.StringRequest
|
||||||
import com.android.volley.toolbox.Volley
|
import com.android.volley.toolbox.Volley
|
||||||
|
import ru.n08i40k.polytechnic.next.data.MyResult
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
import java.util.concurrent.ExecutionException
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
import javax.net.ssl.SSLContext
|
import javax.net.ssl.SSLContext
|
||||||
import javax.net.ssl.SSLSocketFactory
|
import javax.net.ssl.SSLSocketFactory
|
||||||
@@ -82,3 +87,23 @@ open class RequestBase(
|
|||||||
return headers
|
return headers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <ResultT, RequestT : RequestBase> tryFuture(
|
||||||
|
buildRequest: (RequestFuture<ResultT>) -> RequestT
|
||||||
|
): MyResult<ResultT> {
|
||||||
|
val future = RequestFuture.newFuture<ResultT>()
|
||||||
|
buildRequest(future).send()
|
||||||
|
return tryGet(future)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> tryGet(future: RequestFuture<T>): MyResult<T> {
|
||||||
|
return try {
|
||||||
|
MyResult.Success(future.get())
|
||||||
|
} catch (exception: VolleyError) {
|
||||||
|
MyResult.Failure(exception)
|
||||||
|
} catch (exception: ExecutionException) {
|
||||||
|
MyResult.Failure(exception.cause as VolleyError)
|
||||||
|
} catch (exception: TimeoutException) {
|
||||||
|
MyResult.Failure(exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package ru.n08i40k.polytechnic.next.network.data
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.volley.Response
|
import com.android.volley.Response
|
||||||
import com.android.volley.VolleyError
|
|
||||||
import com.android.volley.toolbox.RequestFuture
|
import com.android.volley.toolbox.RequestFuture
|
||||||
import com.android.volley.toolbox.StringRequest
|
import com.android.volley.toolbox.StringRequest
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -16,6 +15,8 @@ import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetCacheStatusR
|
|||||||
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetCacheStatusResponse
|
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetCacheStatusResponse
|
||||||
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateRequest
|
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateRequest
|
||||||
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateRequestData
|
import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateRequestData
|
||||||
|
import ru.n08i40k.polytechnic.next.network.tryFuture
|
||||||
|
import ru.n08i40k.polytechnic.next.network.tryGet
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
import kotlin.io.encoding.Base64
|
import kotlin.io.encoding.Base64
|
||||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||||
@@ -47,61 +48,58 @@ open class CachedRequest(
|
|||||||
)
|
)
|
||||||
NetworkConnection.getInstance(context).addToRequestQueue(request)
|
NetworkConnection.getInstance(context).addToRequestQueue(request)
|
||||||
|
|
||||||
try {
|
when (val response = tryGet(mainPageFuture)) {
|
||||||
val encodedMainPage =
|
is MyResult.Failure -> response
|
||||||
Base64.Default.encode(mainPageFuture.get().encodeToByteArray())
|
is MyResult.Success -> {
|
||||||
MyResult.Success(encodedMainPage)
|
val encodedMainPage = Base64.Default.encode(response.data.encodeToByteArray())
|
||||||
} catch (exception: Exception) {
|
MyResult.Success(encodedMainPage)
|
||||||
MyResult.Failure(exception)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateMainPage(): MyResult<ScheduleGetCacheStatusResponse> {
|
private suspend fun updateMainPage(): MyResult<ScheduleGetCacheStatusResponse> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
val mainPage = getMainPage()
|
when (val mainPage = getMainPage()) {
|
||||||
|
is MyResult.Failure -> mainPage
|
||||||
if (mainPage is MyResult.Failure)
|
is MyResult.Success -> {
|
||||||
return@withContext mainPage
|
tryFuture {
|
||||||
|
ScheduleUpdateRequest(
|
||||||
val updateFuture = RequestFuture.newFuture<ScheduleGetCacheStatusResponse>()
|
ScheduleUpdateRequestData(mainPage.data),
|
||||||
ScheduleUpdateRequest(
|
context,
|
||||||
ScheduleUpdateRequestData((mainPage as MyResult.Success<String>).data),
|
it,
|
||||||
context,
|
it
|
||||||
updateFuture,
|
)
|
||||||
updateFuture
|
}
|
||||||
).send()
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
MyResult.Success(updateFuture.get())
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
MyResult.Failure(exception)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun send() {
|
override fun send() {
|
||||||
val logger = Logger.getLogger("CachedRequest")
|
val logger = Logger.getLogger("CachedRequest")
|
||||||
|
|
||||||
val repository = appContainer.networkCacheRepository
|
val repository = appContainer.networkCacheRepository
|
||||||
|
|
||||||
val future = RequestFuture.newFuture<ScheduleGetCacheStatusResponse>()
|
|
||||||
|
|
||||||
logger.info("Getting cache status...")
|
logger.info("Getting cache status...")
|
||||||
ScheduleGetCacheStatusRequest(context, future, future).send()
|
|
||||||
|
|
||||||
try {
|
val cacheStatusResult = tryFuture {
|
||||||
val response = future.get()
|
ScheduleGetCacheStatusRequest(context, it, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheStatusResult is MyResult.Success) {
|
||||||
|
val cacheStatus = cacheStatusResult.data
|
||||||
|
|
||||||
logger.info("Cache status received successfully!")
|
logger.info("Cache status received successfully!")
|
||||||
|
|
||||||
if (!response.cacheUpdateRequired) {
|
runBlocking {
|
||||||
logger.info("Cache update was not required!")
|
repository.setUpdateDates(
|
||||||
runBlocking {
|
cacheStatus.lastCacheUpdate,
|
||||||
repository.setUpdateDates(response.lastCacheUpdate, response.lastScheduleUpdate)
|
cacheStatus.lastScheduleUpdate
|
||||||
repository.setHash(response.cacheHash)
|
)
|
||||||
}
|
repository.setHash(cacheStatus.cacheHash)
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (cacheStatus.cacheUpdateRequired) {
|
||||||
logger.info("Cache update was required!")
|
logger.info("Cache update was required!")
|
||||||
val updateResult = runBlocking { updateMainPage() }
|
val updateResult = runBlocking { updateMainPage() }
|
||||||
|
|
||||||
@@ -119,16 +117,11 @@ open class CachedRequest(
|
|||||||
|
|
||||||
is MyResult.Failure -> {
|
is MyResult.Failure -> {
|
||||||
logger.warning("Failed to update cache!")
|
logger.warning("Failed to update cache!")
|
||||||
super.getErrorListener()
|
|
||||||
?.onErrorResponse(updateResult.exception.cause as VolleyError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (exception: Exception) {
|
} else {
|
||||||
logger.warning("Failed to get cache status!")
|
logger.warning("Failed to get cache status!")
|
||||||
super.getErrorListener()?.onErrorResponse(exception.cause as VolleyError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val cachedResponse = runBlocking { repository.get(url) }
|
val cachedResponse = runBlocking { repository.get(url) }
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -27,6 +28,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
@@ -46,10 +48,13 @@ fun ExpandableCard(
|
|||||||
|
|
||||||
val transition = rememberTransition(transitionState)
|
val transition = rememberTransition(transitionState)
|
||||||
|
|
||||||
Card(modifier = modifier.clickable {
|
Card(
|
||||||
onExpandedChange()
|
modifier = modifier.clickable {
|
||||||
transitionState.targetState = expanded
|
onExpandedChange()
|
||||||
}) {
|
transitionState.targetState = expanded
|
||||||
|
},
|
||||||
|
shape = RectangleShape
|
||||||
|
) {
|
||||||
Column {
|
Column {
|
||||||
ExpandableCardHeader(title, transition)
|
ExpandableCardHeader(title, transition)
|
||||||
ExpandableCardContent(visible = expanded, content = content)
|
ExpandableCardContent(visible = expanded, content = content)
|
||||||
@@ -83,6 +88,7 @@ private fun ExpandableCardContent(
|
|||||||
enter = enterTransition,
|
enter = enterTransition,
|
||||||
exit = exitTransition
|
exit = exitTransition
|
||||||
) {
|
) {
|
||||||
|
HorizontalDivider()
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.n08i40k.polytechnic.next.ui.main.schedule
|
package ru.n08i40k.polytechnic.next.ui.main.schedule
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -28,7 +29,8 @@ fun DayPager(group: Group = FakeScheduleRepository.exampleGroup) {
|
|||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
contentPadding = PaddingValues(horizontal = 20.dp),
|
contentPadding = PaddingValues(horizontal = 20.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.Top,
|
||||||
|
modifier = Modifier.height(600.dp)
|
||||||
) { page ->
|
) { page ->
|
||||||
DayCard(
|
DayCard(
|
||||||
modifier = Modifier.graphicsLayer {
|
modifier = Modifier.graphicsLayer {
|
||||||
@@ -37,8 +39,8 @@ fun DayPager(group: Group = FakeScheduleRepository.exampleGroup) {
|
|||||||
lerp(
|
lerp(
|
||||||
start = 0.95f, stop = 1f, fraction = 1f - offset.coerceIn(0f, 1f)
|
start = 0.95f, stop = 1f, fraction = 1f - offset.coerceIn(0f, 1f)
|
||||||
).also { scale ->
|
).also { scale ->
|
||||||
scaleX = scale
|
scaleX = 1F - scale + 0.95F
|
||||||
scaleY = scale
|
scaleY = 1F - scale + 0.95F
|
||||||
}
|
}
|
||||||
alpha = lerp(
|
alpha = lerp(
|
||||||
start = 0.5f, stop = 1f, fraction = 1f - offset.coerceIn(0f, 1f)
|
start = 0.5f, stop = 1f, fraction = 1f - offset.coerceIn(0f, 1f)
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
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.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
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
|
||||||
@@ -16,10 +12,7 @@ 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
|
||||||
@@ -35,25 +28,20 @@ fun ScheduleScreen(
|
|||||||
val uiState by scheduleViewModel.uiState.collectAsStateWithLifecycle()
|
val uiState by scheduleViewModel.uiState.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
LoadingContent(
|
LoadingContent(
|
||||||
empty = uiState.isLoading,
|
empty = when (uiState) {
|
||||||
|
is ScheduleUiState.NoSchedule -> uiState.isLoading
|
||||||
|
is ScheduleUiState.HasSchedule -> false
|
||||||
|
},
|
||||||
loading = uiState.isLoading,
|
loading = uiState.isLoading,
|
||||||
onRefresh = { onRefreshSchedule() },
|
onRefresh = { onRefreshSchedule() },
|
||||||
verticalArrangement = Arrangement.Top
|
verticalArrangement = Arrangement.Top
|
||||||
) {
|
) {
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is ScheduleUiState.HasSchedule -> {
|
is ScheduleUiState.HasSchedule -> {
|
||||||
Box {
|
Column {
|
||||||
val networkCacheRepository =
|
val hasSchedule = uiState as ScheduleUiState.HasSchedule
|
||||||
hiltViewModel<MainViewModel>(LocalContext.current as ComponentActivity)
|
UpdateInfo(hasSchedule.lastUpdateAt, hasSchedule.updateDates)
|
||||||
.appContainer
|
DayPager(hasSchedule.group)
|
||||||
.networkCacheRepository
|
|
||||||
|
|
||||||
UpdateInfo(networkCacheRepository)
|
|
||||||
|
|
||||||
Column {
|
|
||||||
Spacer(modifier = Modifier.height(200.dp))
|
|
||||||
DayPager((uiState as ScheduleUiState.HasSchedule).group)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,26 @@
|
|||||||
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.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
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.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
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.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
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.R
|
||||||
import ru.n08i40k.polytechnic.next.data.cache.NetworkCacheRepository
|
import ru.n08i40k.polytechnic.next.UpdateDates
|
||||||
import ru.n08i40k.polytechnic.next.data.cache.impl.FakeNetworkCacheRepository
|
|
||||||
import ru.n08i40k.polytechnic.next.ui.ExpandableCard
|
import ru.n08i40k.polytechnic.next.ui.ExpandableCard
|
||||||
import ru.n08i40k.polytechnic.next.ui.model.ScheduleViewModel
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@@ -40,24 +30,21 @@ fun Date.toString(format: String, locale: Locale = Locale.getDefault()): String
|
|||||||
return formatter.format(this)
|
return formatter.format(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentDateTime(): Date {
|
|
||||||
return Calendar.getInstance().time
|
|
||||||
}
|
|
||||||
|
|
||||||
val expanded = mutableStateOf(false)
|
val expanded = mutableStateOf(false)
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
fun UpdateInfo(networkCacheRepository: NetworkCacheRepository = FakeNetworkCacheRepository()) {
|
fun UpdateInfo(
|
||||||
|
lastUpdateAt: Long = 0,
|
||||||
|
updateDates: UpdateDates = UpdateDates.newBuilder().build()
|
||||||
|
) {
|
||||||
var expanded by remember { expanded }
|
var expanded by remember { expanded }
|
||||||
|
|
||||||
val format = "hh:mm:ss dd.MM.yyyy"
|
val format = "HH:mm:ss dd.MM.yyyy"
|
||||||
|
|
||||||
val updateDates = remember { runBlocking { networkCacheRepository.getUpdateDates() } }
|
val currentDate = Date(lastUpdateAt).toString(format)
|
||||||
|
val cacheUpdateDate = Date(updateDates.cache).toString(format)
|
||||||
val currentDate = remember { getCurrentDateTime().toString(format) }
|
val scheduleUpdateDate = Date(updateDates.schedule).toString(format)
|
||||||
val cacheUpdateDate = remember { Date(updateDates.cache).toString(format) }
|
|
||||||
val scheduleUpdateDate = remember { Date(updateDates.schedule).toString(format) }
|
|
||||||
|
|
||||||
ExpandableCard(
|
ExpandableCard(
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
@@ -69,19 +56,40 @@ fun UpdateInfo(networkCacheRepository: NetworkCacheRepository = FakeNetworkCache
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
) {
|
) {
|
||||||
Row(horizontalArrangement = Arrangement.Center) {
|
Row(
|
||||||
Text(text = stringResource(R.string.last_local_update) + " - ")
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
Text(text = currentDate, fontWeight = FontWeight.Bold)
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.last_local_update))
|
||||||
|
Text(
|
||||||
|
text = currentDate,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(horizontalArrangement = Arrangement.Center) {
|
Row(
|
||||||
Text(text = stringResource(R.string.last_server_cache_update) + " - ")
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
Text(text = cacheUpdateDate, fontWeight = FontWeight.Bold)
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.last_server_cache_update))
|
||||||
|
Text(
|
||||||
|
text = cacheUpdateDate,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(horizontalArrangement = Arrangement.Center) {
|
Row(
|
||||||
Text(text = stringResource(R.string.last_server_schedule_update) + " - ")
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
Text(text = scheduleUpdateDate, fontWeight = FontWeight.Bold)
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.last_server_schedule_update))
|
||||||
|
Text(
|
||||||
|
text = scheduleUpdateDate,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import ru.n08i40k.polytechnic.next.UpdateDates
|
||||||
import ru.n08i40k.polytechnic.next.data.AppContainer
|
import ru.n08i40k.polytechnic.next.data.AppContainer
|
||||||
import ru.n08i40k.polytechnic.next.data.MyResult
|
import ru.n08i40k.polytechnic.next.data.MyResult
|
||||||
import ru.n08i40k.polytechnic.next.model.Group
|
import ru.n08i40k.polytechnic.next.model.Group
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.logging.Logger
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
sealed interface ScheduleUiState {
|
sealed interface ScheduleUiState {
|
||||||
@@ -23,18 +26,22 @@ sealed interface ScheduleUiState {
|
|||||||
|
|
||||||
data class HasSchedule(
|
data class HasSchedule(
|
||||||
val group: Group,
|
val group: Group,
|
||||||
|
val updateDates: UpdateDates,
|
||||||
|
val lastUpdateAt: Long,
|
||||||
override val isLoading: Boolean
|
override val isLoading: Boolean
|
||||||
) : ScheduleUiState
|
) : ScheduleUiState
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class ScheduleViewModelState(
|
private data class ScheduleViewModelState(
|
||||||
val group: Group? = null,
|
val group: Group? = null,
|
||||||
|
val updateDates: UpdateDates? = null,
|
||||||
|
val lastUpdateAt: Long = 0,
|
||||||
val isLoading: Boolean = false
|
val isLoading: Boolean = false
|
||||||
) {
|
) {
|
||||||
fun toUiState(): ScheduleUiState = if (group == null) {
|
fun toUiState(): ScheduleUiState = if (group == null) {
|
||||||
ScheduleUiState.NoSchedule(isLoading)
|
ScheduleUiState.NoSchedule(isLoading)
|
||||||
} else {
|
} else {
|
||||||
ScheduleUiState.HasSchedule(group, isLoading)
|
ScheduleUiState.HasSchedule(group, updateDates!!, lastUpdateAt, isLoading)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +50,7 @@ class ScheduleViewModel @Inject constructor(
|
|||||||
appContainer: AppContainer
|
appContainer: AppContainer
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val scheduleRepository = appContainer.scheduleRepository
|
private val scheduleRepository = appContainer.scheduleRepository
|
||||||
|
private val networkCacheRepository = appContainer.networkCacheRepository
|
||||||
private val viewModelState = MutableStateFlow(ScheduleViewModelState(isLoading = true))
|
private val viewModelState = MutableStateFlow(ScheduleViewModelState(isLoading = true))
|
||||||
|
|
||||||
val uiState = viewModelState
|
val uiState = viewModelState
|
||||||
@@ -61,8 +69,23 @@ class ScheduleViewModel @Inject constructor(
|
|||||||
|
|
||||||
viewModelState.update {
|
viewModelState.update {
|
||||||
when (result) {
|
when (result) {
|
||||||
is MyResult.Success -> it.copy(group = result.data, isLoading = false)
|
is MyResult.Success -> {
|
||||||
is MyResult.Failure -> it.copy(group = null, isLoading = false)
|
val updateDates = networkCacheRepository.getUpdateDates()
|
||||||
|
|
||||||
|
Logger.getLogger("ScheduleViewModel").info("Updating...")
|
||||||
|
|
||||||
|
it.copy(
|
||||||
|
group = result.data,
|
||||||
|
updateDates = updateDates,
|
||||||
|
lastUpdateAt = Date().time,
|
||||||
|
isLoading = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is MyResult.Failure -> it.copy(
|
||||||
|
group = null,
|
||||||
|
isLoading = false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user