improve ui in messages history screen
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M16.5,6.75v10.58c0,2.09 -1.53,3.95 -3.61,4.15 -2.39,0.23 -4.39,-1.64 -4.39,-3.98V5.14c0,-1.31 0.94,-2.5 2.24,-2.63 1.5,-0.15 2.76,1.02 2.76,2.49v10.5c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V6.75c0,-0.41 -0.34,-0.75 -0.75,-0.75s-0.75,0.34 -0.75,0.75v8.61c0,1.31 0.94,2.5 2.24,2.63 1.5,0.15 2.76,-1.02 2.76,-2.49V5.17c0,-2.09 -1.53,-3.95 -3.61,-4.15C9.01,0.79 7,2.66 7,5v12.27c0,2.87 2.1,5.44 4.96,5.71 3.29,0.3 6.04,-2.26 6.04,-5.48V6.75c0,-0.41 -0.34,-0.75 -0.75,-0.75s-0.75,0.34 -0.75,0.75z"/>
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M16.5,6.75v10.58c0,2.09 -1.53,3.95 -3.61,4.15 -2.39,0.23 -4.39,-1.64 -4.39,-3.98V5.14c0,-1.31 0.94,-2.5 2.24,-2.63 1.5,-0.15 2.76,1.02 2.76,2.49v10.5c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V6.75c0,-0.41 -0.34,-0.75 -0.75,-0.75s-0.75,0.34 -0.75,0.75v8.61c0,1.31 0.94,2.5 2.24,2.63 1.5,0.15 2.76,-1.02 2.76,-2.49V5.17c0,-2.09 -1.53,-3.95 -3.61,-4.15C9.01,0.79 7,2.66 7,5v12.27c0,2.87 2.1,5.44 4.96,5.71 3.29,0.3 6.04,-2.26 6.04,-5.48V6.75c0,-0.41 -0.34,-0.75 -0.75,-0.75s-0.75,0.34 -0.75,0.75z" />
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ class LoginViewModelImpl(
|
|||||||
val accessToken = response.accessToken
|
val accessToken = response.accessToken
|
||||||
|
|
||||||
if (userId == null || accessToken == null) {
|
if (userId == null || accessToken == null) {
|
||||||
// TODO: 11/04/2024, Danil Nikolaev: send unknown error event
|
loginError.update { LoginError.Unknown }
|
||||||
return@processState
|
return@processState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -161,15 +161,13 @@ fun LoginScreen(
|
|||||||
val focusManager = LocalFocusManager.current
|
val focusManager = LocalFocusManager.current
|
||||||
val (loginFocusable, passwordFocusable) = FocusRequester.createRefs()
|
val (loginFocusable, passwordFocusable) = FocusRequester.createRefs()
|
||||||
|
|
||||||
// TODO: 13/07/2024, Danil Nikolaev: remove
|
|
||||||
var loginText by remember { mutableStateOf(TextFieldValue(screenState.login)) }
|
var loginText by remember { mutableStateOf(TextFieldValue(screenState.login)) }
|
||||||
val showLoginError = screenState.loginError
|
val showLoginError = screenState.loginError
|
||||||
|
|
||||||
val autoFillEmailHandler = autoFillRequestHandler(
|
val autoFillEmailHandler = autoFillRequestHandler(
|
||||||
autofillTypes = listOf(AutofillType.EmailAddress),
|
autofillTypes = listOf(AutofillType.EmailAddress),
|
||||||
onFill = { value ->
|
onFill = { value ->
|
||||||
loginText =
|
loginText = TextFieldValue(text = value, selection = TextRange(value.length))
|
||||||
TextFieldValue(text = value, selection = TextRange(value.length))
|
|
||||||
onLoginAutoFilled(value)
|
onLoginAutoFilled(value)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -180,8 +178,7 @@ fun LoginScreen(
|
|||||||
val autoFillPasswordHandler = autoFillRequestHandler(
|
val autoFillPasswordHandler = autoFillRequestHandler(
|
||||||
autofillTypes = listOf(AutofillType.Password),
|
autofillTypes = listOf(AutofillType.Password),
|
||||||
onFill = { value ->
|
onFill = { value ->
|
||||||
passwordText =
|
passwordText = TextFieldValue(text = value, selection = TextRange(value.length))
|
||||||
TextFieldValue(text = value, selection = TextRange(value.length))
|
|
||||||
onPasswordAutoFilled(value)
|
onPasswordAutoFilled(value)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -204,7 +204,7 @@ fun ValidationScreen(
|
|||||||
if (newText.text.length > 6) return@TextField
|
if (newText.text.length > 6) return@TextField
|
||||||
|
|
||||||
code = newText
|
code = newText
|
||||||
onCodeInputChanged((newText.text))
|
onCodeInputChanged(newText.text)
|
||||||
},
|
},
|
||||||
label = { Text(text = "Code") },
|
label = { Text(text = "Code") },
|
||||||
placeholder = { Text(text = "Code") },
|
placeholder = { Text(text = "Code") },
|
||||||
|
|||||||
+50
-12
@@ -1,10 +1,12 @@
|
|||||||
package com.meloda.app.fast.messageshistory.presentation
|
package com.meloda.app.fast.messageshistory.presentation
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.animation.core.Animatable
|
import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
@@ -16,6 +18,7 @@ import androidx.compose.foundation.layout.calculateStartPadding
|
|||||||
import androidx.compose.foundation.layout.defaultMinSize
|
import androidx.compose.foundation.layout.defaultMinSize
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.imeNestedScroll
|
import androidx.compose.foundation.layout.imeNestedScroll
|
||||||
import androidx.compose.foundation.layout.imePadding
|
import androidx.compose.foundation.layout.imePadding
|
||||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
@@ -57,9 +60,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
@@ -67,6 +73,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.core.view.HapticFeedbackConstantsCompat
|
import androidx.core.view.HapticFeedbackConstantsCompat
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.meloda.app.fast.datastore.SettingsKeys
|
import com.meloda.app.fast.datastore.SettingsKeys
|
||||||
|
import com.meloda.app.fast.datastore.UserSettings
|
||||||
import com.meloda.app.fast.messageshistory.MessagesHistoryViewModel
|
import com.meloda.app.fast.messageshistory.MessagesHistoryViewModel
|
||||||
import com.meloda.app.fast.messageshistory.MessagesHistoryViewModelImpl
|
import com.meloda.app.fast.messageshistory.MessagesHistoryViewModelImpl
|
||||||
import com.meloda.app.fast.messageshistory.model.ActionMode
|
import com.meloda.app.fast.messageshistory.model.ActionMode
|
||||||
@@ -94,10 +101,14 @@ fun MessagesHistoryRoute(
|
|||||||
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
||||||
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
val userSettings: UserSettings = koinInject()
|
||||||
|
val showEmojiButton by userSettings.showEmojiButton.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
MessagesHistoryScreen(
|
MessagesHistoryScreen(
|
||||||
screenState = screenState,
|
screenState = screenState,
|
||||||
baseError = baseError,
|
baseError = baseError,
|
||||||
canPaginate = canPaginate,
|
canPaginate = canPaginate,
|
||||||
|
showEmojiButton = showEmojiButton,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
onChatMaterialsDropdownItemClicked = onChatMaterialsDropdownItemClicked,
|
onChatMaterialsDropdownItemClicked = onChatMaterialsDropdownItemClicked,
|
||||||
onRefreshDropdownItemClicked = viewModel::onRefresh,
|
onRefreshDropdownItemClicked = viewModel::onRefresh,
|
||||||
@@ -119,6 +130,7 @@ fun MessagesHistoryScreen(
|
|||||||
screenState: MessagesHistoryScreenState = MessagesHistoryScreenState.EMPTY,
|
screenState: MessagesHistoryScreenState = MessagesHistoryScreenState.EMPTY,
|
||||||
baseError: BaseError? = null,
|
baseError: BaseError? = null,
|
||||||
canPaginate: Boolean = false,
|
canPaginate: Boolean = false,
|
||||||
|
showEmojiButton: Boolean = false,
|
||||||
onBack: () -> Unit = {},
|
onBack: () -> Unit = {},
|
||||||
onChatMaterialsDropdownItemClicked: (peerId: Int, conversationMessageId: Int) -> Unit = { _, _ -> },
|
onChatMaterialsDropdownItemClicked: (peerId: Int, conversationMessageId: Int) -> Unit = { _, _ -> },
|
||||||
onRefreshDropdownItemClicked: () -> Unit = {},
|
onRefreshDropdownItemClicked: () -> Unit = {},
|
||||||
@@ -170,6 +182,12 @@ fun MessagesHistoryScreen(
|
|||||||
animationSpec = tween(durationMillis = 50)
|
animationSpec = tween(durationMillis = 50)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var messageBarHeight by remember {
|
||||||
|
mutableStateOf(0.dp)
|
||||||
|
}
|
||||||
|
|
||||||
|
val density = LocalDensity.current
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentWindowInsets = WindowInsets.statusBars,
|
contentWindowInsets = WindowInsets.statusBars,
|
||||||
@@ -294,7 +312,8 @@ fun MessagesHistoryScreen(
|
|||||||
listState = listState,
|
listState = listState,
|
||||||
immutableMessages = ImmutableList.copyOf(screenState.messages),
|
immutableMessages = ImmutableList.copyOf(screenState.messages),
|
||||||
isPaginating = screenState.isPaginating,
|
isPaginating = screenState.isPaginating,
|
||||||
enableAnimations = animationsEnabled
|
enableAnimations = animationsEnabled,
|
||||||
|
messageBarHeight = messageBarHeight
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
@@ -302,6 +321,7 @@ fun MessagesHistoryScreen(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.align(Alignment.BottomStart)
|
.align(Alignment.BottomStart)
|
||||||
.background(Color.Transparent)
|
.background(Color.Transparent)
|
||||||
|
.padding(bottom = 8.dp)
|
||||||
.navigationBarsPadding()
|
.navigationBarsPadding()
|
||||||
.imePadding()
|
.imePadding()
|
||||||
) {
|
) {
|
||||||
@@ -316,22 +336,24 @@ fun MessagesHistoryScreen(
|
|||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.animateContentSize()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.clip(RoundedCornerShape(percent = 50))
|
.clip(RoundedCornerShape(36.dp))
|
||||||
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp)),
|
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp))
|
||||||
verticalAlignment = Alignment.CenterVertically
|
.onGloballyPositioned {
|
||||||
|
messageBarHeight = with(density) {
|
||||||
|
it.size.height.toDp()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
Spacer(modifier = Modifier.width(6.dp))
|
||||||
|
|
||||||
if (
|
if (showEmojiButton) {
|
||||||
preferences.getBoolean(
|
|
||||||
SettingsKeys.KEY_SHOW_EMOJI_BUTTON,
|
|
||||||
SettingsKeys.DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val rotation = remember { Animatable(0f) }
|
val rotation = remember { Animatable(0f) }
|
||||||
|
|
||||||
|
Column(verticalArrangement = Arrangement.Bottom) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
|
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
|
||||||
@@ -359,12 +381,20 @@ fun MessagesHistoryScreen(
|
|||||||
tint = MaterialTheme.colorScheme.primary
|
tint = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var message by remember { mutableStateOf(TextFieldValue(screenState.message)) }
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
value = screenState.message,
|
value = message,
|
||||||
onValueChange = onMessageInputChanged,
|
onValueChange = { newText ->
|
||||||
|
message = newText
|
||||||
|
onMessageInputChanged(newText.text)
|
||||||
|
},
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
unfocusedContainerColor = Color.Transparent,
|
unfocusedContainerColor = Color.Transparent,
|
||||||
focusedContainerColor = Color.Transparent,
|
focusedContainerColor = Color.Transparent,
|
||||||
@@ -380,6 +410,7 @@ fun MessagesHistoryScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Column(verticalArrangement = Arrangement.Bottom) {
|
||||||
IconButton(onClick = onAttachmentButtonClicked) {
|
IconButton(onClick = onAttachmentButtonClicked) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = UiR.drawable.round_attach_file_24),
|
painter = painterResource(id = UiR.drawable.round_attach_file_24),
|
||||||
@@ -389,9 +420,13 @@ fun MessagesHistoryScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
}
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val rotation = remember { Animatable(0f) }
|
val rotation = remember { Animatable(0f) }
|
||||||
|
|
||||||
|
Column(verticalArrangement = Arrangement.Bottom) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (screenState.actionMode == ActionMode.Record) {
|
if (screenState.actionMode == ActionMode.Record) {
|
||||||
@@ -436,6 +471,9 @@ fun MessagesHistoryScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
Spacer(modifier = Modifier.width(6.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -15,6 +15,7 @@ import androidx.compose.material3.CircularProgressIndicator
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.meloda.app.fast.messageshistory.model.UiMessage
|
import com.meloda.app.fast.messageshistory.model.UiMessage
|
||||||
import com.meloda.app.fast.ui.theme.LocalThemeConfig
|
import com.meloda.app.fast.ui.theme.LocalThemeConfig
|
||||||
@@ -32,7 +33,8 @@ fun MessagesList(
|
|||||||
listState: LazyListState,
|
listState: LazyListState,
|
||||||
immutableMessages: ImmutableList<UiMessage>,
|
immutableMessages: ImmutableList<UiMessage>,
|
||||||
isPaginating: Boolean,
|
isPaginating: Boolean,
|
||||||
enableAnimations: Boolean
|
enableAnimations: Boolean,
|
||||||
|
messageBarHeight: Dp
|
||||||
) {
|
) {
|
||||||
val messages = immutableMessages.toList()
|
val messages = immutableMessages.toList()
|
||||||
val currentTheme = LocalThemeConfig.current
|
val currentTheme = LocalThemeConfig.current
|
||||||
@@ -52,7 +54,7 @@ fun MessagesList(
|
|||||||
reverseLayout = true
|
reverseLayout = true
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(68.dp))
|
Spacer(modifier = Modifier.height(messageBarHeight.plus(18.dp)))
|
||||||
Spacer(
|
Spacer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
Reference in New Issue
Block a user