package com.gyf.csams.activity.ui import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.MediaStore import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image import androidx.compose.foundation.border import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import com.google.accompanist.coil.rememberCoilPainter import com.google.accompanist.imageloading.ImageLoadState import com.google.accompanist.insets.ExperimentalAnimatedInsets import com.google.accompanist.insets.navigationBarsWithImePadding import com.gyf.csams.R import com.gyf.csams.activity.model.* import com.gyf.csams.module.ActivityPhotoVo import com.gyf.csams.module.BBSVo import com.gyf.csams.module.TendencyType import com.gyf.csams.module.UserInfoVo import com.gyf.csams.uikit.* import com.gyf.lib.uikit.* import com.gyf.lib.util.Api import com.gyf.lib.util.BottomButton import com.gyf.lib.util.DateTimeUtil.datetimeFormat import com.gyf.lib.util.TokenManager import com.orhanobut.logger.Logger import java.util.* val PHOTO_HEIGHT = 200.dp /** * 活动详情 * */ class ActivityDetailActivity : ComponentActivity() { private val activityId: Int get() { val id = intent.getIntExtra( ActivityDetailActivity::class.java.name, 0 ) return if (id == 0) throw IllegalArgumentException("活动id:${id}不合法,初始化失败") else id } @ExperimentalAnimatedInsets override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { NavBody { nav, scaffoldState -> val model: ActivityDetailViewModel = viewModel() val currentMenuName by model.currentMenu.observeAsState(ActivityDetailMenu.startMenu) Column { TextTopAppBar( nav = nav, currentMenuName = currentMenuName.menuName, menuNames = ActivityDetailMenu.values() ) NavHost( navController = nav, startDestination = ActivityDetailMenu.startMenu.name ) { composable(ActivityDetailMenu.Info.name) { Info() ShowSnackbar(scaffoldState = scaffoldState) model.clickMenu(ActivityDetailMenu.Info) } composable(ActivityDetailMenu.Photo.name) { Photo(nav = nav) ShowSnackbar(scaffoldState = scaffoldState) model.clickMenu(ActivityDetailMenu.Photo) } // composable(ActivityDetailMenu.Member.name) { // Member() // ShowSnackbar(scaffoldState = scaffoldState) // model.clickMenu(ActivityDetailMenu.Member) // } composable(ActivityDetailMenu.BBS.name) { BBS() ShowSnackbar(scaffoldState = scaffoldState) model.clickMenu(ActivityDetailMenu.BBS) } } } } } } /** * 活动信息 * */ @Composable private fun Info( model: ActivityInfoViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel() ) { LaunchedEffect(activityId) { model.load(activityId = activityId) model.checkTendency(activityId = activityId) } MainColumnFrame(background = { Background( image = BackgroundImage.ActivityInfo, alpha = 0.7F ) }) { RectList(modifier = Modifier.weight(0.4F)) ActivityDesc(modifier = Modifier.weight(0.4F)) Spacer(modifier = Modifier.weight(0.05F)) val checkTendency by model.tendency.observeAsState() checkTendency?.apply { val confirmDesc = if (hasLike) R.string.cancel_like else R.string.like_btn val backDesc = if (hasCollect) R.string.cancel_collect else R.string.collect_btn BottomButton( modifier = Modifier.fillMaxWidth(), confirmDesc = confirmDesc, backDesc = backDesc, onConfirm = { model.tendency(type = TendencyType.Like, activityId = activityId) { scaffoldModel.update( message = "${getString(confirmDesc)}${if (it) "成功" else "失败"}", "确认" ) model.checkTendency(activityId = activityId) } }, onBack = { model.tendency(type = TendencyType.Collect, activityId = activityId) { scaffoldModel.update( message = "${getString(backDesc)}${if (it) "成功" else "失败"}", "确认" ) model.checkTendency(activityId = activityId) } }) } Spacer(modifier = Modifier.weight(0.05F)) } } /** * 活动基础信息 * */ @Composable private fun RectList( modifier: Modifier = Modifier, model: ActivityInfoViewModel = viewModel() ) { val activityDetailVo by model.activityDetailVo.observeAsState() activityDetailVo?.let { Card(modifier = modifier, backgroundColor = MaterialTheme.colors.background) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.SpaceAround ) { RectListItem(text = it.associationVo.name) RectListItem(text = it.activityVo.activityName) RectListItem(text = Date(it.activityVo.activityTime).datetimeFormat()) RectListItem(text = it.activityVo.activityAddress) } } } } /** * 列表项 * * @param text */ @Composable private fun RectListItem(text: String) { Row(modifier = Modifier.fillMaxWidth()) { val color = MaterialTheme.colors.secondaryVariant val canvasSize = 30.dp Box(modifier = Modifier.weight(0.5F), contentAlignment = Alignment.Center) { Canvas(modifier = Modifier.size(canvasSize)) { drawCircle(color = color) } } Text(text = text, style = MaterialTheme.typography.h5, modifier = Modifier.weight(0.5F)) } } /** * 活动介绍 * * @param modifier * @param model */ @Composable private fun ActivityDesc( modifier: Modifier = Modifier, model: ActivityInfoViewModel = viewModel() ) { Column(modifier = modifier) { val activityDetailVo by model.activityDetailVo.observeAsState() activityDetailVo?.let { DescCard( modifier = Modifier.weight(0.5F), content = it.activityVo.activityDesc ) } } } /** * 相册 * */ @ExperimentalAnimatedInsets @Composable private fun Photo( model: ActivityPhotoViewModel = viewModel(), infoModel: ActivityInfoViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel(), nav: NavHostController ) { LaunchedEffect(activityId) { model.load(activityId = activityId) } MainColumnFrame(background = { Background( image = BackgroundImage.ActivityPhoto, alpha = 0.7F ) }) { val activityDetailVo by infoModel.activityDetailVo.observeAsState() if (TokenManager.getUserInfo()?.associationVo?.associationId == activityDetailVo?.associationVo?.associationId && TokenManager.getUserInfo()?.isHead == true) { var photoUri: Uri? by remember { mutableStateOf(null) } Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { val resultLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { when (it.resultCode) { RESULT_OK -> { it.data?.data?.apply { Logger.i("uri=$this") photoUri = this } } } } IconButton(onClick = { resultLauncher.launch( Intent( Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI ) ) }) { Icon( painter = painterResource(id = R.drawable.ic_upload), contentDescription = null ) } } photoUri?.let { val status by model.name.statusForm.observeAsState() AlertDialog(onDismissRequest = { /*TODO*/ }, title = { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center ) { Text(text = "上传照片") } }, text = { val photo = rememberCoilPainter(request = it) Column { BaseTextField( modifier = Modifier.navigationBarsWithImePadding(), form = model.name ) Image( // modifier=Modifier.weight(0.5F), painter = photo, contentDescription = null, contentScale = ContentScale.Inside ) } }, buttons = { BottomButton( modifier = Modifier.fillMaxWidth(), confirmDesc = R.string.upload_btn, backDesc = R.string.close_btn, onConfirm = { model.upload(activityId = activityId, uri = it) { photoUri = null scaffoldModel.update(it, actionLabel = "关闭提示") { nav.navigate(ActivityDetailMenu.Photo.name) } } }, onBack = { photoUri = null }, enabled = status == FormStatus.Valid ) } ) } Spacer(modifier = Modifier.height(10.dp)) } Box( modifier = Modifier .fillMaxSize() .padding(10.dp) .border( width = 1.dp, color = MaterialTheme.colors.background ) ) { val listState = rememberLazyListState() val photos by model.data.observeAsState() photos?.let { LazyColumn(state = listState) { it.chunked(2).forEach { item { Spacer(modifier = Modifier.height(20.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { Spacer(modifier = Modifier.weight(0.05F)) PhotoItem( vo = it[0], modifier = Modifier .weight(0.4F) .height(PHOTO_HEIGHT) ) Spacer(modifier = Modifier.weight(0.1F)) if (it.size == 2) { PhotoItem( vo = it[1], modifier = Modifier .weight(0.4F) .height(PHOTO_HEIGHT) ) } else { Spacer(modifier = Modifier.weight(0.4F)) } Spacer(modifier = Modifier.weight(0.05F)) } Spacer(modifier = Modifier.height(20.dp)) } } } } } } } @Composable private fun PhotoItem(modifier: Modifier = Modifier, vo: ActivityPhotoVo) { Box( modifier = modifier.border(width = 1.dp, color = MaterialTheme.colors.onBackground), contentAlignment = Alignment.Center ) { val photo = rememberCoilPainter(request = Api.buildUrl(vo.url)) when (photo.loadState) { is ImageLoadState.Loading -> CircularProgressIndicator(Modifier.align(Alignment.Center)) is ImageLoadState.Success -> Image( painter = photo, contentDescription = vo.name, ) else -> Text(text = "图片加载失败") } } } /** * 活动成员 * */ @Composable private fun Member( model: ActivityMemberViewModel = viewModel() ) { MainColumnFrame(background = { Background( image = BackgroundImage.ActivityMember, alpha = 0.7F ) }) { val data by model.data.observeAsState() data?.apply { Spacer(modifier = Modifier.height(5.dp)) Row( modifier = Modifier .fillMaxWidth() .weight(0.2F), horizontalArrangement = Arrangement.Center ) { Box(contentAlignment = Alignment.Center) { Image( painter = painterResource(id = R.drawable.persion_name_border), contentDescription = null ) Text(text = first().name) } } Spacer(modifier = Modifier.height(5.dp)) Box( modifier = Modifier .fillMaxWidth() .weight(0.8F) .padding(10.dp) .border(width = 1.dp, color = MaterialTheme.colors.onBackground) ) { val listState = rememberLazyListState() drop(1).let { LazyColumn(state = listState) { it.chunked(2).forEach { item { Spacer(modifier = Modifier.height(10.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { Spacer(modifier = Modifier.weight(0.05F)) Participant(vo = it[0], modifier = Modifier.weight(0.4F)) Spacer(modifier = Modifier.weight(0.1F)) if (it.size == 2) { Participant( vo = it[1], modifier = Modifier.weight(0.4F) ) } else { Spacer(modifier = Modifier.weight(0.4F)) } Spacer(modifier = Modifier.weight(0.05F)) } Spacer(modifier = Modifier.height(10.dp)) } } } if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { TODO("加载更多") } } } } } } @Composable private fun Participant(modifier: Modifier = Modifier, vo: UserInfoVo) { Box(modifier = modifier, contentAlignment = Alignment.Center) { Image( painter = painterResource(id = R.drawable.participant_border), contentDescription = null, // contentScale = ContentScale.FillBounds, // modifier = Modifier.fillMaxSize() ) Text(text = vo.name) } } /** * 交流区 * */ @Composable private fun BBS( model: BBSViewModel = viewModel(), bbsCommentModel: BBSCommentModel = viewModel() ) { LaunchedEffect(activityId) { bbsCommentModel.activityId = this@ActivityDetailActivity.activityId model.load(activityId) } MainColumnFrame(background = { Background( image = BackgroundImage.ActivityBBS, alpha = 0.7F ) }) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 10.dp), horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically ) { IconButton(onClick = { bbsCommentModel.openDialog() }) { Icon( painter = painterResource(id = R.drawable.ic_editor), contentDescription = null ) } } SendComment(model = bbsCommentModel) { model.load(activityId) } Box( modifier = Modifier .weight(0.9F) .padding(10.dp) .border(width = 1.dp, color = MaterialTheme.colors.onBackground) ) { val listState = rememberLazyListState() val data by model.data.observeAsState() LazyColumn(state = listState) { data?.forEach { item { BBSItem(vo = it) Spacer(modifier = Modifier.height(5.dp)) Divider(color = MaterialTheme.colors.onBackground) } } } } } } @Composable private fun BBSItem(vo: BBSVo) { Column { Row( modifier = Modifier .fillMaxWidth() .padding(10.dp) ) { Card( backgroundColor = MaterialTheme.colors.secondaryVariant, modifier = Modifier.weight(0.5F) ) { Column( modifier = Modifier.height(50.dp), verticalArrangement = Arrangement.SpaceEvenly ) { Text(text = vo.user.name) Text(text = Date(vo.createTime).datetimeFormat()) } } Spacer(modifier = Modifier.weight(0.5F)) } Card( backgroundColor = MaterialTheme.colors.background, modifier = Modifier.padding(10.dp) ) { Text( text = vo.content, modifier = Modifier .fillMaxWidth() .height(100.dp) ) } } } }