mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Add icons to profile
Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
@@ -12,19 +12,25 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.Chat
|
||||||
|
import androidx.compose.material.icons.filled.AlternateEmail
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material.icons.filled.CalendarMonth
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material.icons.filled.Info
|
||||||
|
import androidx.compose.material.icons.filled.Link
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.MediumTopAppBar
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -34,17 +40,20 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Rect
|
import androidx.compose.ui.geometry.Rect
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.layout.positionInRoot
|
import androidx.compose.ui.layout.positionInRoot
|
||||||
import androidx.compose.ui.platform.ClipboardManager
|
import androidx.compose.ui.platform.ClipboardManager
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.pr0gramm3r101.components.Category
|
||||||
|
import com.pr0gramm3r101.components.CategoryDefaults
|
||||||
|
import com.pr0gramm3r101.components.ListItem
|
||||||
import ru.fromchat.api.ApiClient
|
import ru.fromchat.api.ApiClient
|
||||||
import ru.fromchat.api.UserProfile
|
import ru.fromchat.api.UserProfile
|
||||||
import ru.fromchat.ui.chat.Avatar
|
import ru.fromchat.ui.chat.Avatar
|
||||||
|
import ru.fromchat.ui.scaleOnPress
|
||||||
|
|
||||||
private data class ProfileUiState(
|
private data class ProfileUiState(
|
||||||
val profile: UserProfile? = null,
|
val profile: UserProfile? = null,
|
||||||
@@ -87,16 +96,28 @@ fun ProfileScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier,
|
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
MediumTopAppBar(
|
||||||
title = { Text(text = "Profile") },
|
title = { Text("Profile") },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = onBack) {
|
Box(
|
||||||
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = "Back")
|
modifier = Modifier
|
||||||
|
.scaleOnPress(0.96f, onClick = onBack)
|
||||||
|
.padding(12.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = "Back",
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
@@ -104,7 +125,6 @@ fun ProfileScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(innerPadding)
|
.padding(innerPadding)
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
) {
|
||||||
val errorMessage = state.error
|
val errorMessage = state.error
|
||||||
val profile = state.profile
|
val profile = state.profile
|
||||||
@@ -117,9 +137,11 @@ fun ProfileScreen(
|
|||||||
sharedAvatarKey != null
|
sharedAvatarKey != null
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
.fillMaxSize()
|
||||||
verticalArrangement = Arrangement.Top
|
.verticalScroll(rememberScrollState())
|
||||||
|
,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
when {
|
when {
|
||||||
useSharedAvatar -> {
|
useSharedAvatar -> {
|
||||||
@@ -191,8 +213,7 @@ fun ProfileScreen(
|
|||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = displayName,
|
text = displayName,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge
|
||||||
textAlign = TextAlign.Center
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
@@ -201,47 +222,115 @@ fun ProfileScreen(
|
|||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Category(Modifier.padding(top = 0.dp)) {
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
Row(
|
||||||
) {
|
modifier = Modifier.fillMaxWidth(),
|
||||||
Button(
|
horizontalArrangement = Arrangement.spacedBy(0.dp)
|
||||||
onClick = { onChat(profile.id) },
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
) {
|
) {
|
||||||
Text(text = "Chat")
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.scaleOnPress(0.96f) { onChat(profile.id) },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier.padding(vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.Chat,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(28.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
|
Text(
|
||||||
|
text = "Chat",
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.scaleOnPress(0.96f) {
|
||||||
|
clipboardManager.setText(AnnotatedString(profileLink))
|
||||||
|
state = state.copy(linkStatus = "Link copied!")
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier.padding(vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Link,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(28.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
|
Text(
|
||||||
|
text = "Link",
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Button(
|
}
|
||||||
onClick = {
|
|
||||||
clipboardManager.setText(AnnotatedString(profileLink))
|
state.linkStatus?.let { status ->
|
||||||
state = state.copy(linkStatus = "Link copied!")
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = status,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Category(Modifier.padding(top = 16.dp), title = "Details") {
|
||||||
|
ListItem(
|
||||||
|
headline = "Username",
|
||||||
|
supportingText = profile.username,
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.AlternateEmail,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.weight(1f)
|
divider = true,
|
||||||
) {
|
dividerColor = CategoryDefaults.dividerColor,
|
||||||
Text(text = "Link")
|
dividerThickness = CategoryDefaults.dividerThickness
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
|
||||||
state.linkStatus?.let {
|
if (!profile.bio.isNullOrBlank()) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
ListItem(
|
||||||
Text(text = it, style = MaterialTheme.typography.bodySmall)
|
headline = "Bio",
|
||||||
}
|
supportingText = profile.bio,
|
||||||
|
divider = true,
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
dividerColor = CategoryDefaults.dividerColor,
|
||||||
|
dividerThickness = CategoryDefaults.dividerThickness,
|
||||||
Card(modifier = Modifier.fillMaxWidth()) {
|
leadingContent = {
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Icon(
|
||||||
ProfileField(label = "Username", value = profile.username)
|
imageVector = Icons.Filled.Info,
|
||||||
Divider(modifier = Modifier.padding(vertical = 8.dp))
|
contentDescription = null
|
||||||
ProfileField(label = "Bio", value = profile.bio ?: "No bio")
|
)
|
||||||
Divider(modifier = Modifier.padding(vertical = 8.dp))
|
}
|
||||||
ProfileField(label = "Member since", value = profile.createdAt ?: "Unknown")
|
|
||||||
Divider(modifier = Modifier.padding(vertical = 8.dp))
|
|
||||||
ProfileField(
|
|
||||||
label = "Status",
|
|
||||||
value = if ((profile.deleted == true) || (profile.suspended == true)) "Suspended/Deleted" else "Active"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListItem(
|
||||||
|
headline = "Member since",
|
||||||
|
supportingText = profile.createdAt,
|
||||||
|
divider = true,
|
||||||
|
dividerColor = CategoryDefaults.dividerColor,
|
||||||
|
dividerThickness = CategoryDefaults.dividerThickness,
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.CalendarMonth,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,19 +338,3 @@ fun ProfileScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun ProfileField(label: String, value: String) {
|
|
||||||
Column(modifier = Modifier.fillMaxWidth()) {
|
|
||||||
Text(
|
|
||||||
text = label,
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = Color.Gray
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
|
||||||
Text(
|
|
||||||
text = value,
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user