新增动态

This commit is contained in:
2024-07-30 15:49:59 +08:00
parent 0730fdea68
commit f28236b365
7 changed files with 161 additions and 43 deletions

View File

@@ -21,8 +21,12 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Build
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -30,6 +34,7 @@ import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -45,6 +50,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import coil.compose.AsyncImage
import com.aiosman.riderpro.LocalNavController
@@ -56,33 +62,53 @@ import com.aiosman.riderpro.ui.composables.AnimatedCounter
import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun MomentsList() {
val model = MomentViewModel
var dataFlow = model.momentsFlow
var moments = dataFlow.collectAsLazyPagingItems()
val scope = rememberCoroutineScope()
LazyColumn {
items(moments.itemCount) { idx ->
val momentItem = moments[idx] ?: return@items
MomentCard(momentItem = momentItem,
onAddComment = {
scope.launch {
model.onAddComment(momentItem.id)
}
},
onLikeClick = {
scope.launch {
if (momentItem.liked) {
model.dislikeMoment(momentItem.id)
} else {
model.likeMoment(momentItem.id)
var refreshing by remember { mutableStateOf(false) }
moments.loadState
val state = rememberPullRefreshState(refreshing, onRefresh = {
model.refreshPager()
})
LaunchedEffect(moments.loadState) {
if (moments.loadState.refresh is LoadState.Loading) {
refreshing = true
} else {
refreshing = false
}
}
Box(Modifier.pullRefresh(state)) {
LazyColumn {
items(moments.itemCount) { idx ->
val momentItem = moments[idx] ?: return@items
MomentCard(momentItem = momentItem,
onAddComment = {
scope.launch {
model.onAddComment(momentItem.id)
}
},
onLikeClick = {
scope.launch {
if (momentItem.liked) {
model.dislikeMoment(momentItem.id)
} else {
model.likeMoment(momentItem.id)
}
}
}
})
)
}
}
PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter))
}
}
@@ -366,10 +392,7 @@ fun MomentBottomOperateRowGroup(
modifier = Modifier.size(24.dp),
liked = momentItem.liked
) {
onLikeClick()
}
}
}

View File

@@ -25,7 +25,6 @@ object MomentViewModel : ViewModel() {
private val _momentsFlow = MutableStateFlow<PagingData<MomentItem>>(PagingData.empty())
val momentsFlow = _momentsFlow.asStateFlow()
val accountService: AccountService = TestAccountServiceImpl()
init {
viewModelScope.launch {
val profile = accountService.getMyAccountProfile()
@@ -42,6 +41,22 @@ object MomentViewModel : ViewModel() {
}
}
}
fun refreshPager() {
viewModelScope.launch {
val profile = accountService.getMyAccountProfile()
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
MomentPagingSource(
MomentRemoteDataSource(momentService),
timelineId = profile.id
)
}
).flow.cachedIn(viewModelScope).collectLatest {
_momentsFlow.value = it
}
}
}
fun updateLikeCount(id: Int) {
val currentPagingData = _momentsFlow.value

View File

@@ -38,15 +38,20 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewModelScope
import coil.compose.AsyncImage
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch
@Preview
@@ -54,6 +59,7 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController
fun NewPostScreen() {
val model = NewPostViewModel
val systemUiController = rememberSystemUiController()
val navController = LocalNavController.current
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(color = Color.Transparent)
}
@@ -64,7 +70,12 @@ fun NewPostScreen() {
modifier = Modifier
.fillMaxSize()
) {
NewPostTopBar()
NewPostTopBar {
model.viewModelScope.launch {
model.createMoment()
navController.popBackStack()
}
}
NewPostTextField("Share your adventure…", NewPostViewModel.textContent) {
NewPostViewModel.textContent = it
}
@@ -72,11 +83,10 @@ fun NewPostScreen() {
AdditionalPostItem()
}
}
}
@Composable
fun NewPostTopBar() {
fun NewPostTopBar(onSendClick: () -> Unit = {}) {
val navController = LocalNavController.current
Box(
modifier = Modifier
@@ -89,18 +99,21 @@ fun NewPostTopBar() {
Image(
painter = painterResource(id = R.drawable.rider_pro_close),
contentDescription = "Back",
modifier = Modifier.size(24.dp).clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
navController.popBackStack()
}
modifier = Modifier
.size(24.dp)
.noRippleClickable {
navController.popBackStack()
}
)
Spacer(modifier = Modifier.weight(1f))
Image(
painter = painterResource(id = R.drawable.rider_pro_send_post),
contentDescription = "Send",
modifier = Modifier.size(24.dp)
modifier = Modifier
.size(24.dp)
.noRippleClickable {
onSendClick()
}
)
}
}
@@ -134,14 +147,15 @@ fun NewPostTextField(hint: String, value: String, onValueChange: (String) -> Uni
@Composable
fun AddImageGrid() {
val context = LocalContext.current
var imageUriList by remember { mutableStateOf(listOf<String>()) }
val model = NewPostViewModel
val pickImageLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val uri = result.data?.data
if (uri != null) {
imageUriList = imageUriList + uri.toString()
model.imageUriList += uri.toString()
}
}
}
@@ -159,16 +173,17 @@ fun AddImageGrid() {
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
imageUriList.forEach {
Image(
painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
contentDescription = "Add Image",
model.imageUriList.forEach {
AsyncImage(
it,
contentDescription = "Image",
modifier = Modifier
.size(110.dp)
.background(Color(0xFFFFFFFF))
.drawBehind {
drawRoundRect(color = Color(0xFF999999), style = stroke)
}
},
contentScale = ContentScale.Crop
)
}
Box(

View File

@@ -2,19 +2,33 @@ package com.aiosman.riderpro.ui.post
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.aiosman.riderpro.data.MomentService
import com.aiosman.riderpro.data.TestMomentServiceImpl
import com.aiosman.riderpro.ui.modification.Modification
import kotlinx.coroutines.launch
object NewPostViewModel : ViewModel() {
var momentService: MomentService = TestMomentServiceImpl()
var textContent by mutableStateOf("")
var searchPlaceAddressResult by mutableStateOf<SearchPlaceAddressResult?>(null)
var modificationList by mutableStateOf<List<Modification>>(listOf())
var imageUriList by mutableStateOf(listOf<String>())
fun asNewPost() {
textContent = ""
searchPlaceAddressResult = null
modificationList = listOf()
}
suspend fun createMoment() {
momentService.createMoment(
content = textContent,
authorId = 1,
imageUriList = imageUriList
)
}
}