Release 0.2.0 (#150)

Release Notes

* Bumped haze, agp, and guava dependencies
* Implemented ordering functionality for friends list
* Added scroll to top feature in friends and conversations screens
* Improved messages handling
* Fixed coloring issues
* Cache improvements
* Implemented logout functionality
* Implemented new authorization flow (no auto-token re-request)
* Added support for sticker pack preview attachments
* Bump LongPoll to version 19
* Markdown support for messages bubbles
* Adjust app name font size based on screen width

---------

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
2025-04-04 21:47:05 +03:00
committed by GitHub
parent 0eb3146428
commit 82fb78e9ea
279 changed files with 9171 additions and 4517 deletions
@@ -33,13 +33,13 @@ interface CreateChatViewModel {
val currentOffset: StateFlow<Int>
val canPaginate: StateFlow<Boolean>
val isChatCreated: StateFlow<Int?>
val isChatCreated: StateFlow<Long?>
fun onPaginationConditionsMet()
fun onRefresh()
fun onErrorConsumed()
fun toggleFriendSelection(userId: Int)
fun toggleFriendSelection(userId: Long)
fun onTitleTextInputChanged(newTitle: String)
@@ -62,7 +62,7 @@ class CreateChatViewModelImpl(
override val currentOffset = MutableStateFlow(0)
override val canPaginate = MutableStateFlow(false)
override val isChatCreated = MutableStateFlow<Int?>(null)
override val isChatCreated = MutableStateFlow<Long?>(null)
private val useContactNames: Boolean = userSettings.useContactNames.value
@@ -84,7 +84,7 @@ class CreateChatViewModelImpl(
baseError.setValue { null }
}
override fun toggleFriendSelection(userId: Int) {
override fun toggleFriendSelection(userId: Long) {
val newSelectionList = screenState.value.selectedFriendsIds.toMutableList()
if (newSelectionList.contains(userId)) {
@@ -9,7 +9,7 @@ data class CreateChatScreenState(
val isPaginating: Boolean,
val isPaginationExhausted: Boolean,
val friends: List<UiFriend>,
val selectedFriendsIds: List<Int>,
val selectedFriendsIds: List<Long>,
val chatTitle: String
) {
companion object {
@@ -1,24 +1,28 @@
package dev.meloda.fast.conversations.navigation
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import dev.meloda.fast.conversations.CreateChatViewModel
import dev.meloda.fast.conversations.CreateChatViewModelImpl
import dev.meloda.fast.conversations.presentation.CreateChatRoute
import dev.meloda.fast.ui.extensions.sharedViewModel
import kotlinx.serialization.Serializable
import org.koin.compose.viewmodel.koinViewModel
@Serializable
object CreateChat
fun NavGraphBuilder.createChatScreen(
onChatCreated: (Int) -> Unit,
onChatCreated: (Long) -> Unit,
navController: NavController,
) {
composable<CreateChat> {
val viewModel: CreateChatViewModel =
it.sharedViewModel<CreateChatViewModelImpl>(navController = navController)
val context = LocalContext.current
val viewModel: CreateChatViewModel = koinViewModel<CreateChatViewModelImpl>(
viewModelStoreOwner = context as AppCompatActivity
)
CreateChatRoute(
onError = {
@@ -34,7 +34,7 @@ fun CreateChatItem(
friend: UiFriend,
maxLines: Int,
isSelected: Boolean,
onItemClicked: (Int) -> Unit
onItemClicked: (Long) -> Unit
) {
Row(
modifier = modifier
@@ -39,7 +39,7 @@ fun CreateChatList(
maxLines: Int,
modifier: Modifier,
padding: PaddingValues,
onItemClicked: (Int) -> Unit,
onItemClicked: (Long) -> Unit,
onTitleTextInputChanged: (String) -> Unit
) {
val coroutineScope = rememberCoroutineScope()
@@ -1,6 +1,7 @@
package dev.meloda.fast.conversations.presentation
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
@@ -67,6 +68,7 @@ import dev.meloda.fast.ui.components.ErrorView
import dev.meloda.fast.ui.components.FullScreenLoader
import dev.meloda.fast.ui.components.IconButton
import dev.meloda.fast.ui.components.NoItemsView
import dev.meloda.fast.ui.components.VkErrorView
import dev.meloda.fast.ui.theme.LocalHazeState
import dev.meloda.fast.ui.theme.LocalThemeConfig
import dev.meloda.fast.ui.util.isScrollingUp
@@ -76,11 +78,9 @@ import dev.meloda.fast.ui.R as UiR
fun CreateChatRoute(
onError: (BaseError) -> Unit,
onBack: () -> Unit,
onChatCreated: (Int) -> Unit,
onChatCreated: (Long) -> Unit,
viewModel: CreateChatViewModel
) {
val context = LocalContext.current
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
@@ -88,7 +88,7 @@ fun CreateChatRoute(
LaunchedEffect(isChatCreated) {
if (isChatCreated != null) {
onChatCreated(isChatCreated ?: -1)
onChatCreated(isChatCreated ?: -1L)
viewModel.onNavigatedBack()
}
}
@@ -121,7 +121,7 @@ fun CreateChatScreen(
onBack: () -> Unit = {},
onRefresh: () -> Unit = {},
onCreateChatButtonClicked: () -> Unit = {},
onItemClicked: (Int) -> Unit = {},
onItemClicked: (Long) -> Unit = {},
onTitleTextInputChanged: (String) -> Unit = {}
) {
val currentTheme = LocalThemeConfig.current
@@ -148,20 +148,24 @@ fun CreateChatScreen(
val hazeState = LocalHazeState.current
val toolbarColorAlpha by animateFloatAsState(
targetValue = if (!listState.canScrollBackward) 1f else 0f,
val topBarContainerColorAlpha by animateFloatAsState(
targetValue = if (!currentTheme.enableBlur || !listState.canScrollBackward) 1f else 0f,
label = "toolbarColorAlpha",
animationSpec = tween(durationMillis = 50)
animationSpec = tween(
durationMillis = 200,
easing = FastOutLinearInEasing
)
)
val toolbarContainerColor by animateColorAsState(
val topBarContainerColor by animateColorAsState(
targetValue =
if (currentTheme.enableBlur || !listState.canScrollBackward)
MaterialTheme.colorScheme.surface
else
MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
if (currentTheme.enableBlur || !listState.canScrollBackward) MaterialTheme.colorScheme.surface
else MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
label = "toolbarColorAlpha",
animationSpec = tween(durationMillis = 50)
animationSpec = tween(
durationMillis = 200,
easing = FastOutLinearInEasing
)
)
Scaffold(
@@ -171,11 +175,7 @@ fun CreateChatScreen(
Column(
modifier = Modifier
.fillMaxWidth()
.background(
toolbarContainerColor.copy(
alpha = if (currentTheme.enableBlur) toolbarColorAlpha else 1f
)
)
.background(topBarContainerColor.copy(alpha = topBarContainerColorAlpha))
.then(
if (currentTheme.enableBlur) {
Modifier.hazeEffect(
@@ -205,11 +205,7 @@ fun CreateChatScreen(
style = MaterialTheme.typography.headlineSmall
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = toolbarContainerColor.copy(
alpha = 0f
)
),
colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
modifier = Modifier.fillMaxWidth(),
)
@@ -272,23 +268,7 @@ fun CreateChatScreen(
) { padding ->
when {
baseError != null -> {
when (baseError) {
is BaseError.SessionExpired -> {
ErrorView(
text = stringResource(UiR.string.session_expired),
buttonText = stringResource(UiR.string.action_log_out),
onButtonClick = onSessionExpiredLogOutButtonClicked
)
}
is BaseError.SimpleError -> {
ErrorView(
text = baseError.message,
buttonText = stringResource(UiR.string.try_again),
onButtonClick = onRefresh
)
}
}
VkErrorView(baseError = baseError)
}
screenState.isLoading && screenState.friends.isEmpty() -> FullScreenLoader()