fixes and improvements

This commit is contained in:
2025-03-21 02:35:57 +03:00
parent 2c8536a9da
commit 797e966b65
9 changed files with 81 additions and 31 deletions
@@ -86,6 +86,8 @@ class MainViewModelImpl(
BaseError.SessionExpired -> { BaseError.SessionExpired -> {
isNeedToReplaceWithAuth.update { true } isNeedToReplaceWithAuth.update { true }
} }
is BaseError.SimpleError -> Unit // TODO: 21-Mar-25, Danil Nikolaev: show error in ui
} }
} }
@@ -6,4 +6,6 @@ import androidx.compose.runtime.Immutable
sealed class BaseError { sealed class BaseError {
data object SessionExpired : BaseError() data object SessionExpired : BaseError()
data class SimpleError(val message: String) : BaseError()
} }
@@ -1,7 +1,7 @@
package dev.meloda.fast.model.api.data package dev.meloda.fast.model.api.data
import dev.meloda.fast.model.api.domain.VkVideoDomain
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import dev.meloda.fast.model.api.domain.VkVideoDomain
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class VkVideoData( data class VkVideoData(
@@ -12,7 +12,7 @@ data class VkVideoData(
val duration: Int, val duration: Int,
val date: Int, val date: Int,
val comments: Int?, val comments: Int?,
val description: String, val description: String?,
val player: String?, val player: String?,
val added: Int?, val added: Int?,
val type: String, val type: String,
@@ -20,9 +20,9 @@ data class VkVideoData(
val access_key: String?, val access_key: String?,
val owner_id: Int, val owner_id: Int,
val is_favorite: Boolean?, val is_favorite: Boolean?,
val image: List<Image>, val image: List<Image>?,
val first_frame: List<FirstFrame>?, val first_frame: List<FirstFrame>?,
val files: File?, val files: File?
) : VkAttachmentData { ) : VkAttachmentData {
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
@@ -67,7 +67,7 @@ data class VkVideoData(
fun toDomain() = VkVideoDomain( fun toDomain() = VkVideoDomain(
id = id, id = id,
ownerId = owner_id, ownerId = owner_id,
images = image.map { it.asVideoImage() }, images = image.orEmpty().map { it.asVideoImage() },
firstFrames = first_frame, firstFrames = first_frame,
accessKey = access_key, accessKey = access_key,
title = title title = title
@@ -46,8 +46,13 @@ class ResponseConverterFactory(private val converter: JsonConverter) : Converter
return successModel return successModel
}, },
onFailure = { failure -> onFailure = { failure ->
if(failure is JsonDataException) { if (failure is JsonDataException) {
throw failure throw ApiException(
RestApiError(
errorCode = -1,
errorMsg = failure.message.orEmpty()
)
)
} }
val isUnit = successType == Unit::class.java val isUnit = successType == Unit::class.java
@@ -1,6 +1,7 @@
package dev.meloda.fast.network package dev.meloda.fast.network
enum class VkErrorCode(val code: Int) { enum class VkErrorCode(val code: Int) {
WTF(-1),
UNKNOWN_ERROR(1), UNKNOWN_ERROR(1),
APP_DISABLED(2), APP_DISABLED(2),
UNKNOWN_METHOD(3), UNKNOWN_METHOD(3),
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer 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.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -22,7 +23,9 @@ fun ErrorView(
onButtonClick: (() -> Unit)? = null, onButtonClick: (() -> Unit)? = null,
) { ) {
Column( Column(
modifier = modifier.fillMaxSize(), modifier = modifier
.fillMaxSize()
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
@@ -62,8 +62,8 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.haze import dev.chrisbanes.haze.hazeEffect
import dev.chrisbanes.haze.hazeChild import dev.chrisbanes.haze.hazeSource
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
import dev.chrisbanes.haze.materials.HazeMaterials import dev.chrisbanes.haze.materials.HazeMaterials
import dev.meloda.fast.chatmaterials.ChatMaterialsViewModel import dev.meloda.fast.chatmaterials.ChatMaterialsViewModel
@@ -137,7 +137,7 @@ fun ChatMaterialsScreen(
) )
} }
val titles = listOf("Photos", "Videos", "Audios", "Files", "Links") val titles = listOf("Photos", "Videos", "Audios")//, "Files", "Links")
val listState = rememberLazyListState() val listState = rememberLazyListState()
val gridState = rememberLazyGridState() val gridState = rememberLazyGridState()
@@ -179,7 +179,7 @@ fun ChatMaterialsScreen(
modifier = Modifier modifier = Modifier
.then( .then(
if (currentTheme.enableBlur) { if (currentTheme.enableBlur) {
Modifier.hazeChild( Modifier.hazeEffect(
state = hazeState, state = hazeState,
style = hazeStyle style = hazeStyle
) )
@@ -311,7 +311,7 @@ fun ChatMaterialsScreen(
modifier = Modifier modifier = Modifier
.then( .then(
if (currentTheme.enableBlur) { if (currentTheme.enableBlur) {
Modifier.haze(state = hazeState) Modifier.hazeSource(state = hazeState)
} else { } else {
Modifier Modifier
} }
@@ -346,7 +346,7 @@ fun ChatMaterialsScreen(
modifier = Modifier modifier = Modifier
.then( .then(
if (currentTheme.enableBlur) { if (currentTheme.enableBlur) {
Modifier.haze(state = hazeState) Modifier.hazeSource(state = hazeState)
} else { } else {
Modifier Modifier
} }
@@ -134,6 +134,7 @@ class ConversationsViewModelImpl(
} }
override fun onRefresh() { override fun onRefresh() {
baseError.setValue { null }
loadConversations(offset = 0) loadConversations(offset = 0)
} }
@@ -273,17 +274,7 @@ class ConversationsViewModelImpl(
conversationsUseCase.getConversations(count = LOAD_COUNT, offset = offset) conversationsUseCase.getConversations(count = LOAD_COUNT, offset = offset)
.listenValue(viewModelScope) { state -> .listenValue(viewModelScope) { state ->
state.processState( state.processState(
error = { error -> error = ::handleError,
if (error is State.Error.ApiError) {
when (error.errorCode) {
VkErrorCode.USER_AUTHORIZATION_FAILED -> {
baseError.setValue { BaseError.SessionExpired }
}
else -> Unit
}
}
},
success = { response -> success = { response ->
val itemsCountSufficient = response.size == LOAD_COUNT val itemsCountSufficient = response.size == LOAD_COUNT
canPaginate.setValue { itemsCountSufficient } canPaginate.setValue { itemsCountSufficient }
@@ -339,6 +330,40 @@ class ConversationsViewModelImpl(
} }
} }
private fun handleError(error: State.Error) {
when (error) {
is State.Error.ApiError -> {
when (error.errorCode) {
VkErrorCode.USER_AUTHORIZATION_FAILED -> {
baseError.setValue { BaseError.SessionExpired }
}
else -> {
baseError.setValue {
BaseError.SimpleError(message = error.errorMessage)
}
}
}
}
State.Error.ConnectionError -> {
baseError.setValue {
BaseError.SimpleError(message = "Connection error")
}
}
State.Error.InternalError -> {
baseError.setValue {
BaseError.SimpleError(message = "Internal error")
}
}
State.Error.UnknownError -> {
baseError.setValue {
BaseError.SimpleError(message = "Unknown error")
}
}
else -> Unit
}
}
private fun deleteConversation(peerId: Int) { private fun deleteConversation(peerId: Int) {
conversationsUseCase.delete(peerId).listenValue(viewModelScope) { state -> conversationsUseCase.delete(peerId).listenValue(viewModelScope) { state ->
state.processState( state.processState(
@@ -339,7 +339,9 @@ fun ConversationsScreen(
} }
) { padding -> ) { padding ->
when { when {
baseError is BaseError.SessionExpired -> { baseError != null -> {
when (baseError) {
is BaseError.SessionExpired -> {
ErrorView( ErrorView(
text = "Session expired", text = "Session expired",
buttonText = "Log out", buttonText = "Log out",
@@ -347,6 +349,16 @@ fun ConversationsScreen(
) )
} }
is BaseError.SimpleError -> {
ErrorView(
text = baseError.message,
buttonText = "Try again",
onButtonClick = onRefresh
)
}
}
}
screenState.isLoading && screenState.conversations.isEmpty() -> FullScreenLoader() screenState.isLoading && screenState.conversations.isEmpty() -> FullScreenLoader()
else -> { else -> {