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
@@ -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,