You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
csamsclient/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt

595 lines
22 KiB

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)
)
}
}
}
}