move all ui-related classes and files to ui module
This commit is contained in:
@@ -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)
|
||||
|
||||
+3
-3
@@ -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()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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(
|
||||
|
||||
+5
-5
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
+8
-8
@@ -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(
|
||||
|
||||
+2
-2
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user