|
|
@@ -5,23 +5,75 @@ import android.content.Context
|
|
|
import android.content.Intent
|
|
|
import android.content.pm.PackageManager
|
|
|
import android.os.Build
|
|
|
+import android.view.WindowManager
|
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
|
+import androidx.compose.foundation.background
|
|
|
+import androidx.compose.foundation.border
|
|
|
+import androidx.compose.foundation.clickable
|
|
|
+import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
|
+import androidx.compose.foundation.layout.Box
|
|
|
import androidx.compose.foundation.layout.Column
|
|
|
+import androidx.compose.foundation.layout.FlowRow
|
|
|
import androidx.compose.foundation.layout.PaddingValues
|
|
|
-import androidx.compose.material3.Button
|
|
|
+import androidx.compose.foundation.layout.Row
|
|
|
+import androidx.compose.foundation.layout.Spacer
|
|
|
+import androidx.compose.foundation.layout.fillMaxSize
|
|
|
+import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
+import androidx.compose.foundation.layout.height
|
|
|
+import androidx.compose.foundation.layout.heightIn
|
|
|
+import androidx.compose.foundation.layout.offset
|
|
|
+import androidx.compose.foundation.layout.padding
|
|
|
+import androidx.compose.foundation.layout.size
|
|
|
+import androidx.compose.foundation.shape.CircleShape
|
|
|
+import androidx.compose.foundation.shape.RoundedCornerShape
|
|
|
+import androidx.compose.foundation.text.BasicTextField
|
|
|
+import androidx.compose.foundation.text.KeyboardOptions
|
|
|
+import androidx.compose.material3.Icon
|
|
|
+import androidx.compose.material3.LocalTextStyle
|
|
|
+import androidx.compose.material3.MaterialTheme
|
|
|
+import androidx.compose.material3.RadioButton
|
|
|
import androidx.compose.material3.Text
|
|
|
import androidx.compose.runtime.Composable
|
|
|
+import androidx.compose.runtime.LaunchedEffect
|
|
|
+import androidx.compose.runtime.SideEffect
|
|
|
+import androidx.compose.runtime.collectAsState
|
|
|
+import androidx.compose.runtime.getValue
|
|
|
+import androidx.compose.runtime.remember
|
|
|
+import androidx.compose.ui.Alignment
|
|
|
+import androidx.compose.ui.Modifier
|
|
|
+import androidx.compose.ui.draw.clip
|
|
|
+import androidx.compose.ui.draw.rotate
|
|
|
+import androidx.compose.ui.graphics.Color
|
|
|
+import androidx.compose.ui.graphics.SolidColor
|
|
|
+import androidx.compose.ui.platform.LocalContext
|
|
|
+import androidx.compose.ui.res.painterResource
|
|
|
+import androidx.compose.ui.text.font.FontWeight
|
|
|
+import androidx.compose.ui.text.input.KeyboardType
|
|
|
+import androidx.compose.ui.text.style.TextAlign
|
|
|
+import androidx.compose.ui.unit.dp
|
|
|
+import androidx.compose.ui.unit.sp
|
|
|
+import androidx.compose.ui.window.Dialog
|
|
|
+import androidx.compose.ui.window.DialogProperties
|
|
|
+import androidx.lifecycle.viewmodel.compose.viewModel
|
|
|
+import coil.compose.AsyncImage
|
|
|
+import com.iscs.bozzys.R
|
|
|
+import com.iscs.bozzys.api.User
|
|
|
import com.iscs.bozzys.ui.common.PageBase
|
|
|
import com.iscs.bozzys.ui.common.Title
|
|
|
-import com.iscs.bozzys.utils.LogUtil
|
|
|
+import com.iscs.bozzys.ui.pages.compose.CardContainer
|
|
|
+import com.iscs.bozzys.ui.pages.vm.VMProfile
|
|
|
+import com.iscs.bozzys.ui.theme.Main
|
|
|
+import com.iscs.bozzys.ui.theme.Text
|
|
|
import com.iscs.bozzys.utils.SystemUtil.uriToFile
|
|
|
import java.io.File
|
|
|
|
|
|
/**
|
|
|
* 打开用户中心
|
|
|
*/
|
|
|
-fun Context.openPageProfile() {
|
|
|
- startActivity(Intent(this, PageProfile::class.java))
|
|
|
+fun Context.openPageProfile(user: User) {
|
|
|
+ startActivity(Intent(this, PageProfile::class.java).apply {
|
|
|
+ putExtra("user", user)
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -51,17 +103,352 @@ class PageProfile : PageBase() {
|
|
|
imageLauncher.launch("image/*")
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 从页面中获取用户数据
|
|
|
+ */
|
|
|
+ private fun getUserInfoFromIntent(): User {
|
|
|
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
|
+ intent.getSerializableExtra("user", User::class.java) ?: User()
|
|
|
+ } else {
|
|
|
+ @Suppress("DEPRECATION")
|
|
|
+ (intent.getSerializableExtra("user") as? User) ?: User()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Composable
|
|
|
override fun GetViews(pv: PaddingValues) {
|
|
|
- Column() {
|
|
|
- Title(pv, "个人中心")
|
|
|
- Button({
|
|
|
- pickerImage {
|
|
|
- LogUtil.i("xiaoming", "$it")
|
|
|
+ val vm: VMProfile = viewModel()
|
|
|
+ val state by vm.state.collectAsState()
|
|
|
+ LaunchedEffect(Unit) {
|
|
|
+ vm.toast.initToast()
|
|
|
+ vm.loading.initLoading()
|
|
|
+ vm.init(getUserInfoFromIntent())
|
|
|
+ }
|
|
|
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
|
|
+ Title(pv, "个人信息")
|
|
|
+ // 头像信息
|
|
|
+ CardContainer(modifier = Modifier.padding(16.dp), topRadius = 16.dp, bottomRadius = 16.dp) {
|
|
|
+ Column {
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(80.dp)
|
|
|
+ .clickable { pickerImage { vm.updateUserAvatar(it) } }
|
|
|
+ .padding(horizontal = 12.dp),
|
|
|
+ verticalAlignment = Alignment.CenterVertically
|
|
|
+ ) {
|
|
|
+ Text("头像", fontSize = 16.sp, fontWeight = FontWeight.Bold, color = Text)
|
|
|
+ Spacer(modifier = Modifier.weight(1f))
|
|
|
+ AsyncImage(
|
|
|
+ model = state.user.avatar, contentDescription = null, modifier = Modifier
|
|
|
+ .size(52.dp)
|
|
|
+ .clip(CircleShape)
|
|
|
+ )
|
|
|
+ Icon(
|
|
|
+ painter = painterResource(R.drawable.back),
|
|
|
+ contentDescription = null,
|
|
|
+ tint = Color(0xFFBBBBBB),
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(start = 5.dp)
|
|
|
+ .size(14.dp)
|
|
|
+ .rotate(180f)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 其他属性
|
|
|
+ CardContainer(
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(horizontal = 16.dp)
|
|
|
+ .padding(bottom = 16.dp), topRadius = 16.dp, bottomRadius = 16.dp
|
|
|
+ ) {
|
|
|
+ Column {
|
|
|
+ // 用户名
|
|
|
+ UserInfoItem("用户名", state.user.nickname) {
|
|
|
+ vm.showModifyDialog("修改用户名", "nickname" to state.user.nickname)
|
|
|
+ }
|
|
|
+ SpacerLine()
|
|
|
+ // 手机号
|
|
|
+ UserInfoItem("手机号", state.user.mobile?.ifEmpty { "点击绑定" } ?: "点击绑定") {
|
|
|
+ vm.showModifyDialog("修改手机号", "mobile" to (state.user.mobile ?: ""))
|
|
|
+ }
|
|
|
+ SpacerLine()
|
|
|
+ // 邮箱
|
|
|
+ UserInfoItem("邮箱", state.user.email?.ifEmpty { "点击绑定" } ?: "点击绑定") {
|
|
|
+ vm.showModifyDialog("修改邮箱", "email" to (state.user.email ?: ""))
|
|
|
+ }
|
|
|
+ SpacerLine()
|
|
|
+ // 性别
|
|
|
+ UserInfoItem("性别", if (state.user.sex != 2) "男" else "女") {
|
|
|
+ vm.showModifyDialog("选择性别", "sex" to "${state.user.sex}")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ProfileDialog(
|
|
|
+ show = state.showModifyDialog,
|
|
|
+ title = state.modifyDialogTitle,
|
|
|
+ {
|
|
|
+ vm.hideModifyDialog()
|
|
|
+ vm.updateUserInfo()
|
|
|
+ },
|
|
|
+ { vm.hideModifyDialog() }) {
|
|
|
+ // 修改非性别的参数
|
|
|
+ if (state.modifyKv.first != "sex") BasicTextField(
|
|
|
+ state.modifyKv.second,
|
|
|
+ onValueChange = { vm.onModifyValueChanged(it) },
|
|
|
+ Modifier
|
|
|
+ .padding(vertical = 16.dp, horizontal = 10.dp)
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(46.dp)
|
|
|
+ .border(1.dp, shape = RoundedCornerShape(6.dp), color = Color(0xFFE5E6EB))
|
|
|
+ .padding(horizontal = 10.dp),
|
|
|
+ singleLine = true,
|
|
|
+ textStyle = LocalTextStyle.current.copy(fontSize = 16.sp, lineHeight = 20.sp),
|
|
|
+ decorationBox = { innerTextField ->
|
|
|
+ Box(contentAlignment = Alignment.CenterStart) {
|
|
|
+ innerTextField()
|
|
|
+ if (state.modifyKv.second.isEmpty()) {
|
|
|
+ val text = when (state.modifyKv.first) {
|
|
|
+ "nickname" -> "请输入用户名"
|
|
|
+ "mobile" -> "请输入手机号"
|
|
|
+ "email" -> "请输入邮箱"
|
|
|
+ else -> "请输入"
|
|
|
+ }
|
|
|
+ Text(
|
|
|
+ text,
|
|
|
+ color = Color(0xFF9CA3AF),
|
|
|
+ fontSize = 16.sp,
|
|
|
+ lineHeight = 20.sp,
|
|
|
+ modifier = Modifier.offset(y = (-1).dp)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cursorBrush = SolidColor(Main),
|
|
|
+ keyboardOptions = KeyboardOptions(keyboardType = if (state.modifyKv.first == "mobile") KeyboardType.Number else KeyboardType.Text)
|
|
|
+ )
|
|
|
+ if (state.modifyKv.first == "sex") {
|
|
|
+ FlowRow(
|
|
|
+ Modifier
|
|
|
+ .padding(horizontal = 10.dp, vertical = 16.dp)
|
|
|
+ .fillMaxWidth()
|
|
|
+ .heightIn(max = 120.dp)
|
|
|
+ ) {
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .clip(RoundedCornerShape(12.dp))
|
|
|
+ .clickable(onClick = { vm.onModifyValueChanged("1") })
|
|
|
+ .padding(horizontal = 10.dp, vertical = 5.dp),
|
|
|
+ verticalAlignment = Alignment.CenterVertically
|
|
|
+ ) {
|
|
|
+ RadioButton(
|
|
|
+ selected = state.modifyKv.second != "2",
|
|
|
+ onClick = null,
|
|
|
+ modifier = Modifier.size(14.dp),
|
|
|
+ )
|
|
|
+ Text(
|
|
|
+ text = "男",
|
|
|
+ fontSize = 15.sp,
|
|
|
+ modifier = Modifier.padding(start = 10.dp),
|
|
|
+ color = Text
|
|
|
+ )
|
|
|
+ }
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .clip(RoundedCornerShape(12.dp))
|
|
|
+ .clickable(onClick = { vm.onModifyValueChanged("2") })
|
|
|
+ .padding(horizontal = 10.dp, vertical = 5.dp),
|
|
|
+ verticalAlignment = Alignment.CenterVertically
|
|
|
+ ) {
|
|
|
+ RadioButton(
|
|
|
+ selected = state.modifyKv.second == "2",
|
|
|
+ onClick = null,
|
|
|
+ modifier = Modifier.size(14.dp),
|
|
|
+ )
|
|
|
+ Text(
|
|
|
+ text = "女",
|
|
|
+ fontSize = 15.sp,
|
|
|
+ modifier = Modifier.padding(start = 10.dp),
|
|
|
+ color = Text
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Composable
|
|
|
+ fun UserInfoItem(title: String, desc: String, click: () -> Unit) {
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(60.dp)
|
|
|
+ .clickable { click() }
|
|
|
+ .padding(horizontal = 12.dp),
|
|
|
+ verticalAlignment = Alignment.CenterVertically
|
|
|
+ ) {
|
|
|
+ Text(title, fontSize = 16.sp, fontWeight = FontWeight.Bold, color = Text)
|
|
|
+ Spacer(modifier = Modifier.weight(1f))
|
|
|
+ Text(desc, fontSize = 15.sp, color = Color(0xFF666666))
|
|
|
+ Icon(
|
|
|
+ painter = painterResource(R.drawable.back),
|
|
|
+ contentDescription = null,
|
|
|
+ tint = Color(0xFFBBBBBB),
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(start = 5.dp)
|
|
|
+ .size(14.dp)
|
|
|
+ .rotate(180f)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分割线
|
|
|
+ */
|
|
|
+ @Composable
|
|
|
+ fun SpacerLine() {
|
|
|
+ Spacer(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(1.dp)
|
|
|
+ .background(Color.Gray.copy(alpha = 0.2f))
|
|
|
+ .padding(horizontal = 12.dp)
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ @Composable
|
|
|
+ fun ProfileDialog(
|
|
|
+ show: Boolean,
|
|
|
+ title: String = "",
|
|
|
+ onConfirm: () -> Unit,
|
|
|
+ onDismiss: () -> Unit,
|
|
|
+ content: @Composable () -> Unit
|
|
|
+ ) {
|
|
|
+ val ctx = LocalContext.current
|
|
|
+ if (!show || ctx !is PageBase) return
|
|
|
+
|
|
|
+ LaunchedEffect(Unit) {
|
|
|
+ ctx.setNavigationLight(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ Dialog(
|
|
|
+ onDismissRequest = onDismiss,
|
|
|
+ properties = DialogProperties(decorFitsSystemWindows = false)
|
|
|
+ ) {
|
|
|
+ val activityWindow = ctx.window
|
|
|
+ val dialogWindow = ctx.getDialogWindow()
|
|
|
+ SideEffect {
|
|
|
+ if (activityWindow != null && dialogWindow != null) {
|
|
|
+ val attributes = WindowManager.LayoutParams()
|
|
|
+ // 复制Activity窗口属性
|
|
|
+ attributes.copyFrom(activityWindow.attributes)
|
|
|
+ // 这个一定要设置
|
|
|
+ attributes.type = dialogWindow.attributes.type
|
|
|
+ // 更新窗口属性
|
|
|
+ dialogWindow.attributes = attributes
|
|
|
+ // 设置窗口的宽度和高度,这段代码Dialog源码中就有哦,可以自己去查看
|
|
|
+ dialogWindow.setLayout(
|
|
|
+ activityWindow.decorView.width,
|
|
|
+ activityWindow.decorView.height
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Box(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxSize()
|
|
|
+ .background(Color.Black.copy(alpha = 0.4f))
|
|
|
+ .clickable(
|
|
|
+ indication = null,
|
|
|
+ interactionSource = remember { MutableInteractionSource() },
|
|
|
+ onClick = {}),
|
|
|
+ contentAlignment = Alignment.Center
|
|
|
+ ) {
|
|
|
+ CardContainer(
|
|
|
+ topRadius = 16.dp,
|
|
|
+ bottomRadius = 16.dp,
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth(0.65f)
|
|
|
+ // 防止点击穿透
|
|
|
+ .clickable(
|
|
|
+ indication = null,
|
|
|
+ interactionSource = remember { MutableInteractionSource() },
|
|
|
+ onClick = {})
|
|
|
+ .background(Color.White, RoundedCornerShape(16.dp))
|
|
|
+ ) {
|
|
|
+ Column(Modifier.fillMaxWidth()) {
|
|
|
+ Row(
|
|
|
+ Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(40.dp)
|
|
|
+ .padding(horizontal = 16.dp),
|
|
|
+ verticalAlignment = Alignment.CenterVertically
|
|
|
+ ) {
|
|
|
+ // Spacer(Modifier.size(40.dp))
|
|
|
+ Text(
|
|
|
+ title,
|
|
|
+ fontSize = 16.sp,
|
|
|
+ fontWeight = FontWeight.Bold,
|
|
|
+ color = Text,
|
|
|
+ modifier = Modifier.weight(1f),
|
|
|
+ textAlign = TextAlign.Center
|
|
|
+ )
|
|
|
+// Icon(
|
|
|
+// painter = painterResource(R.drawable.close),
|
|
|
+// contentDescription = null,
|
|
|
+// modifier = Modifier
|
|
|
+// .offset(8.dp, 0.dp)
|
|
|
+// .size(36.dp)
|
|
|
+// .clip(RoundedCornerShape(50))
|
|
|
+// .clickable(onClick = { onDismiss() })
|
|
|
+// .padding(10.dp)
|
|
|
+// )
|
|
|
+ }
|
|
|
+ Spacer(
|
|
|
+ Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(0.5.dp)
|
|
|
+ .background(Color.Black.copy(alpha = 0.05f))
|
|
|
+ )
|
|
|
+ content()
|
|
|
+ Spacer(
|
|
|
+ Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(0.5.dp)
|
|
|
+ .background(Color.Black.copy(alpha = 0.05f))
|
|
|
+ )
|
|
|
+ Row(Modifier.padding(horizontal = 5.dp, vertical = 10.dp)) {
|
|
|
+ Text(
|
|
|
+ "取消", color = Color.White, modifier = Modifier
|
|
|
+ .padding(horizontal = 5.dp)
|
|
|
+ .weight(1f)
|
|
|
+ .clip(RoundedCornerShape(6.dp))
|
|
|
+ .background(Color.Gray.copy(alpha = 0.6f))
|
|
|
+ .clickable(onClick = { onDismiss() })
|
|
|
+ .padding(vertical = 5.dp),
|
|
|
+ textAlign = TextAlign.Center,
|
|
|
+ fontSize = 16.sp,
|
|
|
+ fontWeight = FontWeight.Bold
|
|
|
+ )
|
|
|
+ Text(
|
|
|
+ "确定",
|
|
|
+ color = Color.White,
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(horizontal = 5.dp)
|
|
|
+ .weight(1f)
|
|
|
+ .clip(RoundedCornerShape(6.dp))
|
|
|
+ .background(MaterialTheme.colorScheme.primary)
|
|
|
+ .clickable(onClick = { onConfirm() })
|
|
|
+ .padding(vertical = 5.dp),
|
|
|
+ textAlign = TextAlign.Center,
|
|
|
+ fontSize = 16.sp,
|
|
|
+ fontWeight = FontWeight.Bold
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- }) {
|
|
|
- Text("选择照片")
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
}
|