209 lines
7.8 KiB
Kotlin
209 lines
7.8 KiB
Kotlin
package profiles.presentation
|
|
|
|
import android.net.Uri
|
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
import androidx.activity.result.PickVisualMediaRequest
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.clickable
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.rememberScrollState
|
|
import androidx.compose.foundation.shape.CircleShape
|
|
import androidx.compose.foundation.verticalScroll
|
|
import androidx.compose.material.icons.Icons
|
|
import androidx.compose.material.icons.filled.ArrowBack
|
|
import androidx.compose.material.icons.filled.CameraAlt
|
|
import androidx.compose.material.icons.filled.Check
|
|
import androidx.compose.material3.*
|
|
import androidx.compose.runtime.*
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.draw.clip
|
|
import androidx.compose.ui.graphics.Color
|
|
import androidx.compose.ui.layout.ContentScale
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.text.font.FontWeight
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import coil.compose.AsyncImage
|
|
import core.presentation.components.AppAvatar
|
|
import core.presentation.theme.SoftSquareShape
|
|
import ru.knot.messager.R
|
|
|
|
import android.app.Activity
|
|
import android.content.Intent
|
|
import com.yalantis.ucrop.UCrop
|
|
import core.utils.ImageCropper
|
|
import java.io.File
|
|
import java.util.UUID
|
|
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
@Composable
|
|
fun EditProfileScreen(
|
|
currentDisplayName: String?,
|
|
currentUsername: String,
|
|
currentBio: String?,
|
|
currentAvatarUrl: String?,
|
|
onSave: (displayName: String, bio: String, avatarUri: Uri?) -> Unit,
|
|
onBack: () -> Unit
|
|
) {
|
|
val context = LocalContext.current
|
|
var displayName by remember { mutableStateOf(currentDisplayName ?: "") }
|
|
var bio by remember { mutableStateOf(currentBio ?: "") }
|
|
var selectedImageUri by remember { mutableStateOf<Uri?>(null) }
|
|
|
|
// Лаунчер для результата кропа
|
|
val cropLauncher = rememberLauncherForActivityResult(
|
|
contract = ActivityResultContracts.StartActivityForResult(),
|
|
onResult = { result ->
|
|
if (result.resultCode == Activity.RESULT_OK && result.data != null) {
|
|
selectedImageUri = UCrop.getOutput(result.data!!)
|
|
}
|
|
}
|
|
)
|
|
|
|
// Лаунчер для выбора фото из галереи
|
|
val photoPickerLauncher = rememberLauncherForActivityResult(
|
|
contract = ActivityResultContracts.PickVisualMedia(),
|
|
onResult = { uri ->
|
|
if (uri != null) {
|
|
// После выбора фото запускаем UCrop
|
|
val destinationUri = Uri.fromFile(File(context.cacheDir, "${UUID.randomUUID()}.jpg"))
|
|
val cropIntent = ImageCropper.getCropIntent(context, uri, destinationUri).getIntent(context)
|
|
cropLauncher.launch(cropIntent)
|
|
}
|
|
}
|
|
)
|
|
|
|
Scaffold(
|
|
topBar = {
|
|
TopAppBar(
|
|
title = { Text(stringResource(R.string.edit_profile)) },
|
|
navigationIcon = {
|
|
IconButton(onClick = onBack) {
|
|
Icon(Icons.Default.ArrowBack, contentDescription = stringResource(R.string.back))
|
|
}
|
|
},
|
|
actions = {
|
|
IconButton(onClick = { onSave(displayName, bio, selectedImageUri) }) {
|
|
Icon(Icons.Default.Check, contentDescription = stringResource(R.string.save), tint = MaterialTheme.colorScheme.primary)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
) { paddingValues ->
|
|
Column(
|
|
modifier = Modifier
|
|
.fillMaxSize()
|
|
.padding(paddingValues)
|
|
.verticalScroll(rememberScrollState())
|
|
.padding(24.dp),
|
|
horizontalAlignment = Alignment.CenterHorizontally
|
|
) {
|
|
// Смена фото
|
|
Box(
|
|
modifier = Modifier
|
|
.size(120.dp)
|
|
.clip(SoftSquareShape)
|
|
.background(MaterialTheme.colorScheme.surfaceVariant)
|
|
.clickable {
|
|
photoPickerLauncher.launch(
|
|
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
|
|
)
|
|
},
|
|
contentAlignment = Alignment.Center
|
|
) {
|
|
if (selectedImageUri != null) {
|
|
AsyncImage(
|
|
model = selectedImageUri,
|
|
contentDescription = null,
|
|
modifier = Modifier.fillMaxSize(),
|
|
contentScale = ContentScale.Crop
|
|
)
|
|
} else {
|
|
AppAvatar(
|
|
url = currentAvatarUrl,
|
|
name = currentUsername,
|
|
size = 120.dp
|
|
)
|
|
}
|
|
|
|
// Overlay
|
|
Box(
|
|
modifier = Modifier
|
|
.fillMaxSize()
|
|
.background(Color.Black.copy(alpha = 0.3f)),
|
|
contentAlignment = Alignment.Center
|
|
) {
|
|
Icon(
|
|
Icons.Default.CameraAlt,
|
|
contentDescription = stringResource(R.string.change_photo),
|
|
tint = Color.White
|
|
)
|
|
}
|
|
}
|
|
|
|
TextButton(
|
|
onClick = {
|
|
photoPickerLauncher.launch(
|
|
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
|
|
)
|
|
},
|
|
modifier = Modifier.padding(top = 8.dp)
|
|
) {
|
|
Text(stringResource(R.string.change_photo))
|
|
}
|
|
|
|
Spacer(modifier = Modifier.height(32.dp))
|
|
|
|
// Поля ввода
|
|
OutlinedTextField(
|
|
value = displayName,
|
|
onValueChange = { displayName = it },
|
|
label = { Text(stringResource(R.string.display_name)) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
singleLine = true,
|
|
shape = SoftSquareShape
|
|
)
|
|
|
|
Spacer(modifier = Modifier.height(16.dp))
|
|
|
|
OutlinedTextField(
|
|
value = "@$currentUsername",
|
|
onValueChange = {},
|
|
label = { Text(stringResource(R.string.username_label)) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
enabled = false, // Обычно username меняется отдельно или вообще не меняется
|
|
shape = SoftSquareShape,
|
|
colors = OutlinedTextFieldDefaults.colors(
|
|
disabledBorderColor = MaterialTheme.colorScheme.outlineVariant,
|
|
disabledLabelColor = MaterialTheme.colorScheme.onSurfaceVariant
|
|
)
|
|
)
|
|
|
|
Spacer(modifier = Modifier.height(16.dp))
|
|
|
|
OutlinedTextField(
|
|
value = bio,
|
|
onValueChange = { bio = it },
|
|
label = { Text(stringResource(R.string.bio)) },
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.heightIn(min = 100.dp),
|
|
shape = SoftSquareShape,
|
|
maxLines = 5
|
|
)
|
|
|
|
Spacer(modifier = Modifier.height(32.dp))
|
|
|
|
Button(
|
|
onClick = { onSave(displayName, bio, selectedImageUri) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
shape = SoftSquareShape
|
|
) {
|
|
Text(stringResource(R.string.save))
|
|
}
|
|
}
|
|
}
|
|
}
|