move all ui-related classes and files to ui module

This commit is contained in:
2024-07-15 18:31:58 +03:00
parent 9a1bce5707
commit ee7499f117
171 changed files with 405 additions and 1354 deletions
@@ -49,11 +49,11 @@ import coil.compose.AsyncImage
import com.meloda.app.fast.auth.captcha.CaptchaViewModel
import com.meloda.app.fast.auth.captcha.CaptchaViewModelImpl
import com.meloda.app.fast.auth.captcha.model.CaptchaScreenState
import com.meloda.app.fast.designsystem.ActionInvokeDismiss
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.designsystem.TextFieldErrorText
import com.meloda.app.fast.ui.components.ActionInvokeDismiss
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.components.TextFieldErrorText
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun CaptchaRoute(
@@ -4,8 +4,8 @@ import com.meloda.app.fast.data.State
import com.meloda.app.fast.data.api.oauth.OAuthRepository
import com.meloda.app.fast.network.OAuthErrorDomain
import com.meloda.app.fast.network.ValidationType
import com.meloda.app.fast.network.VkErrorTypes
import com.meloda.app.fast.network.VkOAuthErrors
import com.meloda.app.fast.network.VkOAuthError
import com.meloda.app.fast.network.VkOAuthErrorType
import com.meloda.fast.auth.login.model.AuthInfo
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
@@ -33,7 +33,10 @@ class OAuthUseCaseImpl(
forceSms = forceSms
)
val newState = when (response.error) {
val error = response.error?.let(VkOAuthError::parse)
val errorType = response.errorType?.let(VkOAuthErrorType::parse)
val newState = when (error) {
null -> {
State.Success(
AuthInfo(
@@ -44,11 +47,11 @@ class OAuthUseCaseImpl(
)
}
VkOAuthErrors.FLOOD_CONTROL -> {
VkOAuthError.FLOOD_CONTROL -> {
State.Error.OAuthError(OAuthErrorDomain.TooManyTriesError)
}
VkOAuthErrors.NEED_VALIDATION -> {
VkOAuthError.NEED_VALIDATION -> {
if (response.banInfo != null) {
val info = requireNotNull(response.banInfo)
@@ -76,7 +79,7 @@ class OAuthUseCaseImpl(
}
}
VkOAuthErrors.NEED_CAPTCHA -> {
VkOAuthError.NEED_CAPTCHA -> {
State.Error.OAuthError(
OAuthErrorDomain.CaptchaRequiredError(
captchaSid = response.captchaSid.orEmpty(),
@@ -85,27 +88,29 @@ class OAuthUseCaseImpl(
)
}
VkOAuthErrors.INVALID_CLIENT -> {
VkOAuthError.INVALID_CLIENT -> {
State.Error.OAuthError(OAuthErrorDomain.InvalidCredentialsError)
}
VkOAuthErrors.INVALID_REQUEST -> {
when (response.errorType) {
VkErrorTypes.WRONG_OTP -> {
VkOAuthError.INVALID_REQUEST -> {
when (errorType) {
VkOAuthErrorType.WRONG_OTP -> {
State.Error.OAuthError(OAuthErrorDomain.WrongValidationCode)
}
VkErrorTypes.WRONG_OTP_FORMAT -> {
VkOAuthErrorType.WRONG_OTP_FORMAT -> {
State.Error.OAuthError(OAuthErrorDomain.WrongValidationCodeFormat)
}
else -> {
State.Error.OAuthError(OAuthErrorDomain.UnknownError)
VkOAuthErrorType.PASSWORD_BRUTEFORCE_ATTEMPT -> {
State.Error.OAuthError(OAuthErrorDomain.TooManyTriesError)
}
null -> State.Error.OAuthError(OAuthErrorDomain.UnknownError)
}
}
else -> {
VkOAuthError.UNKNOWN -> {
State.Error.OAuthError(OAuthErrorDomain.UnknownError)
}
}
@@ -51,14 +51,14 @@ import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.meloda.app.fast.common.UiText
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.designsystem.TextFieldErrorText
import com.meloda.app.fast.designsystem.autoFillRequestHandler
import com.meloda.app.fast.designsystem.connectNode
import com.meloda.app.fast.designsystem.defaultFocusChangeAutoFill
import com.meloda.app.fast.designsystem.handleEnterKey
import com.meloda.app.fast.designsystem.handleTabKey
import com.meloda.app.fast.ui.basic.autoFillRequestHandler
import com.meloda.app.fast.ui.basic.connectNode
import com.meloda.app.fast.ui.basic.defaultFocusChangeAutoFill
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.components.TextFieldErrorText
import com.meloda.app.fast.ui.theme.LocalTheme
import com.meloda.app.fast.ui.util.handleEnterKey
import com.meloda.app.fast.ui.util.handleTabKey
import com.meloda.fast.auth.login.LoginViewModel
import com.meloda.fast.auth.login.LoginViewModelImpl
import com.meloda.fast.auth.login.model.CaptchaArguments
@@ -67,7 +67,7 @@ import com.meloda.fast.auth.login.model.LoginScreenState
import com.meloda.fast.auth.login.model.LoginUserBannedArguments
import com.meloda.fast.auth.login.model.LoginValidationArguments
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun LoginRoute(
@@ -31,11 +31,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.ui.theme.LocalTheme
import com.meloda.fast.auth.login.LoginViewModel
import com.meloda.fast.auth.login.LoginViewModelImpl
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun LogoRoute(
@@ -58,8 +58,6 @@ fun LogoRoute(
)
}
// TODO: 13/07/2024, Danil Nikolaev: replace with scaffold?
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun LogoScreen(
@@ -24,7 +24,7 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.userbanned.model.UserBannedScreenState
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Preview
@Composable
@@ -1,12 +1,12 @@
package com.meloda.app.fast.auth.validation
import com.meloda.app.fast.data.State
import com.meloda.app.fast.model.api.responses.SendSmsResponse
import com.meloda.app.fast.model.api.responses.ValidatePhoneResponse
import kotlinx.coroutines.flow.Flow
interface AuthUseCase {
fun sendSms(
fun validatePhone(
validationSid: String
): Flow<State<SendSmsResponse>>
): Flow<State<ValidatePhoneResponse>>
}
@@ -2,26 +2,17 @@ package com.meloda.app.fast.auth.validation
import com.meloda.app.fast.data.State
import com.meloda.app.fast.data.api.auth.AuthRepository
import com.meloda.app.fast.model.api.responses.SendSmsResponse
import com.meloda.app.fast.data.mapToState
import com.meloda.app.fast.model.api.responses.ValidatePhoneResponse
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class AuthUseCaseImpl(
private val authRepository: AuthRepository
) : AuthUseCase {
class AuthUseCaseImpl(private val repository: AuthRepository) : AuthUseCase {
// TODO: 05/05/2024, Danil Nikolaev: implement
override fun sendSms(validationSid: String): Flow<State<SendSmsResponse>> = flow {
// emit(State.Loading)
//
// val newState = authRepository.sendSms(validationSid)
// .fold(
// onSuccess = { response -> State.Success(response) },
// onNetworkFailure = { State.Error.ConnectionError },
// onUnknownFailure = { State.UNKNOWN_ERROR },
// onHttpFailure = { result -> result.error.toStateApiError() },
// onApiFailure = { result -> result.error.toStateApiError() }
// )
// emit(newState)
override fun validatePhone(validationSid: String): Flow<State<ValidatePhoneResponse>> = flow {
emit(State.Loading)
val newState = repository.validatePhone(validationSid).mapToState()
emit(newState)
}
}
@@ -129,7 +129,7 @@ class ValidationViewModelImpl(
}
private fun sendValidationCode() {
authUseCase.sendSms(validationSid.orEmpty())
authUseCase.validatePhone(validationSid.orEmpty())
.listenValue { state ->
state.processState(
error = { error ->
@@ -47,12 +47,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.meloda.app.fast.auth.validation.ValidationViewModel
import com.meloda.app.fast.auth.validation.ValidationViewModelImpl
import com.meloda.app.fast.auth.validation.model.ValidationScreenState
import com.meloda.app.fast.designsystem.ActionInvokeDismiss
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.designsystem.TextFieldErrorText
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.ui.components.ActionInvokeDismiss
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.components.TextFieldErrorText
import com.meloda.app.fast.ui.util.getString
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun ValidationRoute(
@@ -65,8 +65,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.meloda.app.fast.chatmaterials.ChatMaterialsViewModel
import com.meloda.app.fast.chatmaterials.ChatMaterialsViewModelImpl
import com.meloda.app.fast.chatmaterials.model.ChatMaterialsScreenState
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.designsystem.R
import com.meloda.app.fast.ui.R
import com.meloda.app.fast.ui.theme.LocalTheme
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.haze
import dev.chrisbanes.haze.hazeChild
+1 -1
View File
@@ -58,7 +58,7 @@ dependencies {
implementation(libs.haze)
implementation(libs.haze.materials)
// TODO: 03/07/2024, Danil Nikolaev: remove when stable release
// TODO: 03/07/2024, Danil Nikolaev: remove when stable release (lazy column fixes)
implementation("androidx.compose.foundation:foundation:1.7.0-beta04")
implementation(libs.eithernet)
@@ -20,12 +20,12 @@ import com.meloda.app.fast.data.api.conversations.ConversationsUseCase
import com.meloda.app.fast.data.api.messages.MessagesUseCase
import com.meloda.app.fast.data.processState
import com.meloda.app.fast.datastore.UserSettings
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.model.BaseError
import com.meloda.app.fast.model.InteractionType
import com.meloda.app.fast.model.LongPollEvent
import com.meloda.app.fast.model.api.domain.VkConversation
import com.meloda.app.fast.network.VkErrorCodes
import com.meloda.app.fast.network.VkErrorCode
import com.meloda.app.fast.ui.util.ImmutableList
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -232,7 +232,7 @@ class ConversationsViewModelImpl(
error = { error ->
if (error is State.Error.ApiError) {
when (error.errorCode) {
VkErrorCodes.UserAuthorizationFailed -> {
VkErrorCode.USER_AUTHORIZATION_FAILED -> {
baseError.setValue { BaseError.SessionExpired }
}
@@ -1,341 +0,0 @@
package com.meloda.app.fast.conversations
// TODO: 26.08.2023, Danil Nikolaev: rewrite
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.keyframes
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
const val numberOfDots = 3
val dotSize = 6.dp
val dotColor: Color = Color.Blue
const val delayUnit = 300
const val duration = numberOfDots * delayUnit
val spaceBetween = 2.dp
@Composable
fun DotsPulsing() {
@Composable
fun Dot(scale: Float) {
Spacer(
Modifier
.size(dotSize)
.scale(scale)
.background(
color = dotColor,
shape = CircleShape
)
)
}
val infiniteTransition = rememberInfiniteTransition(label = "")
@Composable
fun animateScaleWithDelay(delay: Int) = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 0f,
animationSpec = infiniteRepeatable(animation = keyframes {
durationMillis = delayUnit * numberOfDots
0f at delay using LinearEasing
1f at delay + delayUnit using LinearEasing
0f at delay + duration
}), label = ""
)
val scales = arrayListOf<State<Float>>()
for (i in 0 until numberOfDots) {
scales.add(animateScaleWithDelay(delay = i * delayUnit))
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
scales.forEach {
Dot(it.value)
Spacer(Modifier.width(spaceBetween))
}
}
}
@Composable
fun DotsElastic() {
val minScale = 0.6f
@Composable
fun Dot(scale: Float) {
Spacer(
Modifier
.size(dotSize)
.scale(scaleX = minScale, scaleY = scale)
.background(
color = dotColor,
shape = CircleShape
)
)
}
val infiniteTransition = rememberInfiniteTransition(label = "")
@Composable
fun animateScaleWithDelay(delay: Int) = infiniteTransition.animateFloat(
initialValue = minScale,
targetValue = minScale,
animationSpec = infiniteRepeatable(animation = keyframes {
durationMillis = duration
minScale at delay using LinearEasing
1f at delay + delayUnit using LinearEasing
minScale at delay + duration
}), label = ""
)
val scales = arrayListOf<State<Float>>()
for (i in 0 until numberOfDots) {
scales.add(animateScaleWithDelay(delay = i * delayUnit))
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
scales.forEach {
Dot(it.value)
Spacer(Modifier.width(spaceBetween))
}
}
}
@Composable
fun DotsFlashing(
modifier: Modifier = Modifier,
dotSize: Dp = 6.dp,
dotColor: Color = Color.Blue,
spaceBetween: Dp = 2.dp,
numberOfDots: Int = 3,
) {
val minAlpha = 0.1f
@Composable
fun Dot(alpha: Float) = Spacer(
Modifier
.size(dotSize)
.alpha(alpha)
.background(
color = dotColor, shape = CircleShape
)
)
val infiniteTransition = rememberInfiniteTransition(label = "")
@Composable
fun animateAlphaWithDelay(delay: Int) = infiniteTransition.animateFloat(
initialValue = minAlpha,
targetValue = minAlpha,
animationSpec = infiniteRepeatable(animation = keyframes {
durationMillis = duration
minAlpha at delay using LinearEasing
1f at delay + delayUnit using LinearEasing
minAlpha at delay + duration
}), label = ""
)
val alphas = arrayListOf<State<Float>>()
for (i in 0 until numberOfDots) {
alphas.add(animateAlphaWithDelay(delay = i * delayUnit))
}
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
alphas.forEach {
Dot(it.value)
Spacer(Modifier.width(spaceBetween))
}
}
}
@Composable
fun DotsTyping(
modifier: Modifier = Modifier,
dotSize: Dp = 6.dp,
dotColor: Color = Color.Blue,
spaceBetween: Dp = 2.dp,
numberOfDots: Int = 3,
) {
val maxOffset = (numberOfDots * 2).toFloat()
@Composable
fun Dot(offset: Float) {
Spacer(
Modifier
.size(dotSize)
.offset(y = -offset.dp)
.background(
color = dotColor,
shape = CircleShape
)
)
}
val infiniteTransition = rememberInfiniteTransition(label = "")
@Composable
fun animateOffsetWithDelay(delay: Int) = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 0f,
animationSpec = infiniteRepeatable(animation = keyframes {
durationMillis = duration
0f at delay using LinearEasing
maxOffset at delay + delayUnit using LinearEasing
0f at delay + (duration / 2)
}), label = ""
)
val offsets = arrayListOf<State<Float>>()
for (i in 0 until numberOfDots) {
offsets.add(animateOffsetWithDelay(delay = i * delayUnit))
}
Row(
modifier = modifier.padding(top = maxOffset.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
offsets.forEach {
Dot(it.value)
Spacer(Modifier.width(spaceBetween))
}
}
}
@Composable
fun DotsCollision() {
val maxOffset = 30f
val delayUnit = 500
@Composable
fun Dot(offset: Float) {
Spacer(
Modifier
.size(dotSize)
.offset(x = offset.dp)
.background(
color = dotColor,
shape = CircleShape
)
)
}
val infiniteTransition = rememberInfiniteTransition(label = "")
val offsetLeft by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 0f,
animationSpec = infiniteRepeatable(animation = keyframes {
durationMillis = delayUnit * 3
0f at 0 using LinearEasing
-maxOffset at delayUnit / 2 using LinearEasing
0f at delayUnit
}), label = ""
)
val offsetRight by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 0f,
animationSpec = infiniteRepeatable(animation = keyframes {
durationMillis = delayUnit * 3
0f at delayUnit using LinearEasing
maxOffset at delayUnit + delayUnit / 2 using LinearEasing
0f at delayUnit * 2
}), label = ""
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
modifier = Modifier.padding(horizontal = maxOffset.dp)
) {
Dot(offsetLeft)
Spacer(Modifier.width(spaceBetween))
for (i in 0 until numberOfDots - 2) {
Dot(0f)
Spacer(Modifier.width(spaceBetween))
}
Dot(offsetRight)
}
}
@Preview(showBackground = true)
@Composable
fun DotsPreview() {
Column(
modifier = Modifier
.padding(4.dp)
.fillMaxSize()
) {
val spaceSize = 16.dp
Text(
text = "Dots pulsing", //style = MaterialTheme.typography.h5
)
DotsPulsing()
Spacer(Modifier.height(spaceSize))
Text(
text = "Dots elastic", //style = MaterialTheme.typography.h5
)
DotsElastic()
Spacer(Modifier.height(spaceSize))
Text(
text = "Dots flashing", //style = MaterialTheme.typography.h5
)
DotsFlashing()
Spacer(Modifier.height(spaceSize))
Text(
text = "Dots typing", //style = MaterialTheme.typography.h5
)
DotsTyping()
Spacer(Modifier.height(spaceSize))
Text(
text = "Dots collision", //style = MaterialTheme.typography.h5
)
DotsCollision()
}
}
@@ -2,7 +2,7 @@ package com.meloda.app.fast.conversations.model
import com.meloda.app.fast.common.UiImage
import com.meloda.app.fast.common.UiText
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
sealed class ConversationOption(
val title: UiText,
@@ -3,9 +3,9 @@ package com.meloda.app.fast.conversations.model
import androidx.compose.runtime.Immutable
import androidx.compose.ui.text.AnnotatedString
import com.meloda.app.fast.common.UiImage
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.model.api.PeerType
import com.meloda.app.fast.model.api.domain.VkMessage
import com.meloda.app.fast.ui.util.ImmutableList
@Immutable
data class UiConversation(
@@ -53,13 +53,13 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import com.meloda.app.fast.common.UiImage
import com.meloda.app.fast.conversations.DotsFlashing
import com.meloda.app.fast.conversations.model.ConversationOption
import com.meloda.app.fast.conversations.model.UiConversation
import com.meloda.app.fast.designsystem.ContentAlpha
import com.meloda.app.fast.designsystem.LocalContentAlpha
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.basic.ContentAlpha
import com.meloda.app.fast.ui.basic.LocalContentAlpha
import com.meloda.app.fast.ui.components.DotsFlashing
import com.meloda.app.fast.ui.util.getString
import com.meloda.app.fast.ui.R as UiR
val BirthdayColor = Color(0xffb00b69)
@@ -27,7 +27,7 @@ import com.meloda.app.fast.common.UserConfig
import com.meloda.app.fast.conversations.model.ConversationOption
import com.meloda.app.fast.conversations.model.ConversationsScreenState
import com.meloda.app.fast.conversations.model.UiConversation
import com.meloda.app.fast.designsystem.LocalBottomPadding
import com.meloda.app.fast.ui.theme.LocalBottomPadding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -72,21 +72,21 @@ import com.meloda.app.fast.conversations.ConversationsViewModelImpl
import com.meloda.app.fast.conversations.model.ConversationOption
import com.meloda.app.fast.conversations.model.ConversationsScreenState
import com.meloda.app.fast.conversations.model.UiConversation
import com.meloda.app.fast.designsystem.LocalBottomPadding
import com.meloda.app.fast.designsystem.LocalHazeState
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.designsystem.components.FullScreenLoader
import com.meloda.app.fast.designsystem.isScrollingUp
import com.meloda.app.fast.model.BaseError
import com.meloda.app.fast.ui.ErrorView
import com.meloda.app.fast.ui.components.ErrorView
import com.meloda.app.fast.ui.components.FullScreenLoader
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.theme.LocalBottomPadding
import com.meloda.app.fast.ui.theme.LocalHazeState
import com.meloda.app.fast.ui.theme.LocalTheme
import com.meloda.app.fast.ui.util.isScrollingUp
import dev.chrisbanes.haze.haze
import dev.chrisbanes.haze.hazeChild
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
import dev.chrisbanes.haze.materials.HazeMaterials
import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun ConversationsRoute(
@@ -18,18 +18,18 @@ import com.meloda.app.fast.common.util.TimeUtils
import com.meloda.app.fast.conversations.model.ActionState
import com.meloda.app.fast.conversations.model.UiConversation
import com.meloda.app.fast.data.VkMemoryCache
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.model.InteractionType
import com.meloda.app.fast.model.api.PeerType
import com.meloda.app.fast.model.api.data.AttachmentType
import com.meloda.app.fast.model.api.domain.VkAttachment
import com.meloda.app.fast.model.api.domain.VkConversation
import com.meloda.app.fast.model.api.domain.VkMessage
import com.meloda.app.fast.ui.util.ImmutableList
import java.util.Calendar
import java.util.Locale
import kotlin.math.ln
import kotlin.math.pow
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
fun VkConversation.asPresentation(
resources: Resources,
@@ -11,7 +11,7 @@ import com.meloda.app.fast.friends.model.FriendsScreenState
import com.meloda.app.fast.friends.util.asPresentation
import com.meloda.app.fast.model.BaseError
import com.meloda.app.fast.model.api.domain.VkUser
import com.meloda.app.fast.network.VkErrorCodes
import com.meloda.app.fast.network.VkErrorCode
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
@@ -71,7 +71,7 @@ class FriendsViewModelImpl(
error = { error ->
if (error is State.Error.ApiError) {
when (error.errorCode) {
VkErrorCodes.UserAuthorizationFailed -> {
VkErrorCode.USER_AUTHORIZATION_FAILED -> {
baseError.setValue { BaseError.SessionExpired }
}
@@ -23,7 +23,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import com.meloda.app.fast.designsystem.R
import com.meloda.app.fast.ui.R
import com.meloda.app.fast.friends.model.UiFriend
@Composable
@@ -20,10 +20,10 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.designsystem.LocalBottomPadding
import com.meloda.app.fast.friends.model.FriendsScreenState
import com.meloda.app.fast.friends.model.UiFriend
import com.meloda.app.fast.ui.theme.LocalBottomPadding
import com.meloda.app.fast.ui.util.ImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -50,23 +50,23 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.imageLoader
import coil.request.ImageRequest
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.designsystem.LocalHazeState
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.designsystem.TabItem
import com.meloda.app.fast.designsystem.components.FullScreenLoader
import com.meloda.app.fast.designsystem.components.NoItemsView
import com.meloda.app.fast.friends.FriendsViewModel
import com.meloda.app.fast.friends.FriendsViewModelImpl
import com.meloda.app.fast.friends.model.FriendsScreenState
import com.meloda.app.fast.model.BaseError
import com.meloda.app.fast.ui.ErrorView
import com.meloda.app.fast.ui.components.ErrorView
import com.meloda.app.fast.ui.components.FullScreenLoader
import com.meloda.app.fast.ui.components.NoItemsView
import com.meloda.app.fast.ui.model.TabItem
import com.meloda.app.fast.ui.theme.LocalHazeState
import com.meloda.app.fast.ui.theme.LocalTheme
import com.meloda.app.fast.ui.util.ImmutableList
import dev.chrisbanes.haze.haze
import dev.chrisbanes.haze.hazeChild
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
import dev.chrisbanes.haze.materials.HazeMaterials
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun FriendsRoute(
@@ -7,12 +7,13 @@ import androidx.lifecycle.ViewModel
import com.meloda.app.fast.common.UiText
import com.meloda.app.fast.common.extensions.setValue
import com.meloda.app.fast.common.parseString
import com.meloda.app.fast.designsystem.R
import com.meloda.app.fast.languagepicker.model.LanguagePickerScreenState
import com.meloda.app.fast.languagepicker.model.SelectableLanguage
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import com.meloda.app.fast.ui.R as UiR
interface LanguagePickerViewModel {
val screenState: StateFlow<LanguagePickerScreenState>
@@ -31,23 +32,23 @@ class LanguagePickerViewModelImpl(
val languages = listOf(
Triple(
"",
UiText.Resource(R.string.language_key_system),
UiText.Resource(R.string.language_system)
UiText.Resource(UiR.string.language_key_system),
UiText.Resource(UiR.string.language_system)
),
Triple(
"en-US",
UiText.Resource(R.string.language_key_english),
UiText.Resource(R.string.language_english),
UiText.Resource(UiR.string.language_key_english),
UiText.Resource(UiR.string.language_english),
),
Triple(
"ru-RU",
UiText.Resource(R.string.language_key_russian),
UiText.Resource(R.string.language_russian)
UiText.Resource(UiR.string.language_key_russian),
UiText.Resource(UiR.string.language_russian)
),
Triple(
"uk-UA",
UiText.Resource(R.string.language_key_ukrainian),
UiText.Resource(R.string.language_ukrainian)
UiText.Resource(UiR.string.language_key_ukrainian),
UiText.Resource(UiR.string.language_ukrainian)
)
).map { (key, language, local) ->
Triple(
@@ -59,7 +59,7 @@ import com.meloda.app.fast.languagepicker.LanguagePickerViewModelImpl
import com.meloda.app.fast.languagepicker.model.LanguagePickerScreenState
import com.meloda.app.fast.languagepicker.model.SelectableLanguage
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun LanguagePickerRoute(
@@ -67,13 +67,13 @@ import androidx.compose.ui.unit.dp
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.meloda.app.fast.datastore.SettingsKeys
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.messageshistory.MessagesHistoryViewModel
import com.meloda.app.fast.messageshistory.MessagesHistoryViewModelImpl
import com.meloda.app.fast.messageshistory.model.ActionMode
import com.meloda.app.fast.messageshistory.model.MessagesHistoryScreenState
import com.meloda.app.fast.model.BaseError
import com.meloda.app.fast.ui.theme.LocalTheme
import com.meloda.app.fast.ui.util.ImmutableList
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.hazeChild
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
@@ -81,7 +81,7 @@ import dev.chrisbanes.haze.materials.HazeMaterials
import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel
import org.koin.compose.koinInject
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun MessagesHistoryRoute(
@@ -16,9 +16,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.designsystem.ImmutableList
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.messageshistory.model.UiMessage
import com.meloda.app.fast.ui.theme.LocalTheme
import com.meloda.app.fast.ui.util.ImmutableList
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.haze
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
@@ -7,14 +7,14 @@ import com.meloda.app.fast.common.UserConfig
import com.meloda.app.fast.common.extensions.orDots
import com.meloda.app.fast.common.parseString
import com.meloda.app.fast.data.VkMemoryCache
import com.meloda.app.fast.designsystem.R
import com.meloda.app.fast.ui.R
import com.meloda.app.fast.messageshistory.model.UiMessage
import com.meloda.app.fast.model.api.PeerType
import com.meloda.app.fast.model.api.domain.VkConversation
import com.meloda.app.fast.model.api.domain.VkMessage
import java.text.SimpleDateFormat
import java.util.Locale
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
private fun isAccount(fromId: Int) = fromId == UserConfig.userId
-3
View File
@@ -60,9 +60,6 @@ dependencies {
implementation(libs.haze)
implementation(libs.haze.materials)
// TODO: 03/07/2024, Danil Nikolaev: remove when stable release
implementation("androidx.compose.foundation:foundation:1.7.0-beta04")
implementation(libs.eithernet)
implementation(libs.androidx.navigation.compose)
@@ -9,7 +9,7 @@ import com.meloda.app.fast.data.State
import com.meloda.app.fast.data.api.users.UsersUseCase
import com.meloda.app.fast.data.processState
import com.meloda.app.fast.model.BaseError
import com.meloda.app.fast.network.VkErrorCodes
import com.meloda.app.fast.network.VkErrorCode
import com.meloda.app.fast.profile.model.ProfileScreenState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -37,7 +37,7 @@ class ProfileViewModelImpl(
error = { error ->
if (error is State.Error.ApiError) {
when (error.errorCode) {
VkErrorCodes.UserAuthorizationFailed -> {
VkErrorCode.USER_AUTHORIZATION_FAILED -> {
baseError.setValue { BaseError.SessionExpired }
}
@@ -40,7 +40,7 @@ import com.meloda.app.fast.profile.ProfileViewModelImpl
import com.meloda.app.fast.profile.model.ProfileScreenState
import org.koin.androidx.compose.koinViewModel
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun ProfileRoute(
@@ -23,7 +23,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
interface SettingsViewModel {
@@ -38,9 +38,6 @@ import com.meloda.app.fast.common.UserConfig
import com.meloda.app.fast.datastore.SettingsKeys
import com.meloda.app.fast.datastore.UserSettings
import com.meloda.app.fast.datastore.isUsingDarkMode
import com.meloda.app.fast.designsystem.ActionInvokeDismiss
import com.meloda.app.fast.designsystem.LocalTheme
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.settings.HapticType
import com.meloda.app.fast.settings.SettingsViewModel
import com.meloda.app.fast.settings.SettingsViewModelImpl
@@ -51,6 +48,9 @@ import com.meloda.app.fast.settings.presentation.items.ListSettingsItem
import com.meloda.app.fast.settings.presentation.items.SwitchSettingsItem
import com.meloda.app.fast.settings.presentation.items.TitleSettingsItem
import com.meloda.app.fast.settings.presentation.items.TitleSummarySettingsItem
import com.meloda.app.fast.ui.components.ActionInvokeDismiss
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.theme.LocalTheme
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.haze
import dev.chrisbanes.haze.hazeChild
@@ -58,7 +58,7 @@ import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
import dev.chrisbanes.haze.materials.HazeMaterials
import org.koin.androidx.compose.koinViewModel
import org.koin.compose.koinInject
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.R as UiR
@Composable
fun SettingsRoute(
@@ -23,17 +23,17 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.common.UiText
import com.meloda.app.fast.designsystem.ContentAlpha
import com.meloda.app.fast.designsystem.ImmutableList.Companion.toImmutableList
import com.meloda.app.fast.designsystem.ItemsSelectionType
import com.meloda.app.fast.designsystem.LocalContentAlpha
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.settings.model.OnSettingsChangeListener
import com.meloda.app.fast.settings.model.OnSettingsClickListener
import com.meloda.app.fast.settings.model.OnSettingsLongClickListener
import com.meloda.app.fast.settings.model.SettingsItem
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.basic.ContentAlpha
import com.meloda.app.fast.ui.basic.LocalContentAlpha
import com.meloda.app.fast.ui.components.ItemsSelectionType
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.util.ImmutableList.Companion.toImmutableList
import com.meloda.app.fast.ui.util.getString
import com.meloda.app.fast.ui.R as UiR
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -23,13 +23,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.designsystem.ContentAlpha
import com.meloda.app.fast.designsystem.LocalContentAlpha
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.settings.model.OnSettingsChangeListener
import com.meloda.app.fast.settings.model.OnSettingsClickListener
import com.meloda.app.fast.settings.model.OnSettingsLongClickListener
import com.meloda.app.fast.settings.model.SettingsItem
import com.meloda.app.fast.ui.basic.ContentAlpha
import com.meloda.app.fast.ui.basic.LocalContentAlpha
import com.meloda.app.fast.ui.util.getString
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -32,15 +32,15 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.common.UiText
import com.meloda.app.fast.designsystem.ContentAlpha
import com.meloda.app.fast.designsystem.LocalContentAlpha
import com.meloda.app.fast.designsystem.MaterialDialog
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.settings.model.OnSettingsChangeListener
import com.meloda.app.fast.settings.model.OnSettingsClickListener
import com.meloda.app.fast.settings.model.OnSettingsLongClickListener
import com.meloda.app.fast.settings.model.SettingsItem
import com.meloda.app.fast.designsystem.R as UiR
import com.meloda.app.fast.ui.basic.ContentAlpha
import com.meloda.app.fast.ui.basic.LocalContentAlpha
import com.meloda.app.fast.ui.components.MaterialDialog
import com.meloda.app.fast.ui.util.getString
import com.meloda.app.fast.ui.R as UiR
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -12,8 +12,8 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.settings.model.SettingsItem
import com.meloda.app.fast.ui.util.getString
@Composable
fun TitleSettingsItem(
@@ -22,12 +22,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.meloda.app.fast.designsystem.ContentAlpha
import com.meloda.app.fast.designsystem.LocalContentAlpha
import com.meloda.app.fast.designsystem.getString
import com.meloda.app.fast.settings.model.OnSettingsClickListener
import com.meloda.app.fast.settings.model.OnSettingsLongClickListener
import com.meloda.app.fast.settings.model.SettingsItem
import com.meloda.app.fast.ui.basic.ContentAlpha
import com.meloda.app.fast.ui.basic.LocalContentAlpha
import com.meloda.app.fast.ui.util.getString
@OptIn(ExperimentalFoundationApi::class)
@Composable