更新代码
This commit is contained in:
@@ -101,9 +101,15 @@ class MainActivity : ComponentActivity() {
|
|||||||
val postId = intent.getStringExtra("POST_ID")
|
val postId = intent.getStringExtra("POST_ID")
|
||||||
if (postId != null) {
|
if (postId != null) {
|
||||||
Log.d("MainActivity", "Navigation to Post$postId")
|
Log.d("MainActivity", "Navigation to Post$postId")
|
||||||
navController.navigate(NavigationRoute.Post.route.replace("{id}", postId))
|
navController.navigate(
|
||||||
|
NavigationRoute.Post.route.replace(
|
||||||
|
"{id}",
|
||||||
|
postId
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,8 @@ class CommentRemoteDataSource(
|
|||||||
postUser: Int?,
|
postUser: Int?,
|
||||||
selfNotice: Boolean?,
|
selfNotice: Boolean?,
|
||||||
order: String?,
|
order: String?,
|
||||||
parentCommentId: Int?
|
parentCommentId: Int?,
|
||||||
|
pageSize: Int? = 20
|
||||||
): ListContainer<CommentEntity> {
|
): ListContainer<CommentEntity> {
|
||||||
return commentService.getComments(
|
return commentService.getComments(
|
||||||
pageNumber,
|
pageNumber,
|
||||||
@@ -163,7 +164,8 @@ class CommentRemoteDataSource(
|
|||||||
postUser = postUser,
|
postUser = postUser,
|
||||||
selfNotice = selfNotice,
|
selfNotice = selfNotice,
|
||||||
order = order,
|
order = order,
|
||||||
parentCommentId = parentCommentId
|
parentCommentId = parentCommentId,
|
||||||
|
pageSize = pageSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ data class Moment(
|
|||||||
@SerializedName("commentCount")
|
@SerializedName("commentCount")
|
||||||
val commentCount: Long,
|
val commentCount: Long,
|
||||||
@SerializedName("time")
|
@SerializedName("time")
|
||||||
val time: String
|
val time: String,
|
||||||
|
@SerializedName("isFollowed")
|
||||||
|
val isFollowed: Boolean,
|
||||||
) {
|
) {
|
||||||
fun toMomentItem(): MomentEntity {
|
fun toMomentItem(): MomentEntity {
|
||||||
return MomentEntity(
|
return MomentEntity(
|
||||||
@@ -38,7 +40,7 @@ data class Moment(
|
|||||||
nickname = user.nickName,
|
nickname = user.nickName,
|
||||||
location = "Worldwide",
|
location = "Worldwide",
|
||||||
time = ApiClient.dateFromApiString(time),
|
time = ApiClient.dateFromApiString(time),
|
||||||
followStatus = false,
|
followStatus = isFollowed,
|
||||||
momentTextContent = textContent,
|
momentTextContent = textContent,
|
||||||
momentPicture = R.drawable.default_moment_img,
|
momentPicture = R.drawable.default_moment_img,
|
||||||
likeCount = likeCount.toInt(),
|
likeCount = likeCount.toInt(),
|
||||||
|
|||||||
@@ -46,14 +46,15 @@ class CommentPagingSource(
|
|||||||
postUser = postUser,
|
postUser = postUser,
|
||||||
selfNotice = selfNotice,
|
selfNotice = selfNotice,
|
||||||
order = order,
|
order = order,
|
||||||
parentCommentId = parentCommentId
|
parentCommentId = parentCommentId,
|
||||||
|
pageSize = params.loadSize
|
||||||
)
|
)
|
||||||
LoadResult.Page(
|
LoadResult.Page(
|
||||||
data = comments.list,
|
data = comments.list,
|
||||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||||
nextKey = if (comments.list.isEmpty()) null else comments.page + 1
|
nextKey = if (comments.list.isEmpty()) null else comments.page + 1
|
||||||
)
|
)
|
||||||
} catch (exception: IOException) {
|
} catch (exception: Exception) {
|
||||||
return LoadResult.Error(exception)
|
return LoadResult.Error(exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.aiosman.riderpro.data.MomentService
|
|||||||
import com.aiosman.riderpro.data.ServiceException
|
import com.aiosman.riderpro.data.ServiceException
|
||||||
import com.aiosman.riderpro.data.UploadImage
|
import com.aiosman.riderpro.data.UploadImage
|
||||||
import com.aiosman.riderpro.data.api.ApiClient
|
import com.aiosman.riderpro.data.api.ApiClient
|
||||||
|
import com.aiosman.riderpro.data.parseErrorResponse
|
||||||
import com.aiosman.riderpro.entity.MomentEntity
|
import com.aiosman.riderpro.entity.MomentEntity
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
@@ -165,8 +166,13 @@ class MomentBackend {
|
|||||||
|
|
||||||
suspend fun getMomentById(id: Int): MomentEntity {
|
suspend fun getMomentById(id: Int): MomentEntity {
|
||||||
var resp = ApiClient.api.getPost(id)
|
var resp = ApiClient.api.getPost(id)
|
||||||
var body = resp.body()?.data ?: throw ServiceException("Failed to get moment")
|
if (!resp.isSuccessful) {
|
||||||
return body.toMomentItem()
|
parseErrorResponse(resp.errorBody())?.let {
|
||||||
|
throw it.toServiceException()
|
||||||
|
}
|
||||||
|
throw ServiceException("Failed to get moment")
|
||||||
|
}
|
||||||
|
return resp.body()?.data?.toMomentItem() ?: throw ServiceException("Failed to get moment")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun likeMoment(id: Int) {
|
suspend fun likeMoment(id: Int) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.aiosman.riderpro.ui.comment
|
package com.aiosman.riderpro.ui.comment
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@@ -14,11 +13,8 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.ime
|
import androidx.compose.foundation.layout.ime
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
@@ -30,17 +26,13 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -48,15 +40,11 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
|
||||||
import com.aiosman.riderpro.AppState
|
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.entity.CommentEntity
|
import com.aiosman.riderpro.entity.CommentEntity
|
||||||
import com.aiosman.riderpro.ui.composables.EditCommentBottomModal
|
import com.aiosman.riderpro.ui.composables.EditCommentBottomModal
|
||||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
|
||||||
import com.aiosman.riderpro.ui.post.CommentContent
|
import com.aiosman.riderpro.ui.post.CommentContent
|
||||||
import com.aiosman.riderpro.ui.post.CommentMenuModal
|
import com.aiosman.riderpro.ui.post.CommentMenuModal
|
||||||
import com.aiosman.riderpro.ui.post.CommentsSection
|
|
||||||
import com.aiosman.riderpro.ui.post.CommentsViewModel
|
import com.aiosman.riderpro.ui.post.CommentsViewModel
|
||||||
import com.aiosman.riderpro.ui.post.OrderSelectionComponent
|
import com.aiosman.riderpro.ui.post.OrderSelectionComponent
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.aiosman.riderpro.ui.composables
|
||||||
|
|
||||||
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
|
import androidx.compose.foundation.text.BasicText
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.compose.ui.text.TextLayoutResult
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CustomClickableText(
|
||||||
|
text: AnnotatedString,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
style: TextStyle = TextStyle.Default,
|
||||||
|
softWrap: Boolean = true,
|
||||||
|
overflow: TextOverflow = TextOverflow.Clip,
|
||||||
|
maxLines: Int = Int.MAX_VALUE,
|
||||||
|
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||||
|
onLongPress: () -> Unit = {},
|
||||||
|
onClick: (Int) -> Unit
|
||||||
|
) {
|
||||||
|
val layoutResult = remember { mutableStateOf<TextLayoutResult?>(null) }
|
||||||
|
val pressIndicator = Modifier.pointerInput(onClick) {
|
||||||
|
detectTapGestures(
|
||||||
|
onLongPress = { onLongPress() }
|
||||||
|
) { pos ->
|
||||||
|
layoutResult.value?.let { layoutResult ->
|
||||||
|
onClick(layoutResult.getOffsetForPosition(pos))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicText(
|
||||||
|
text = text,
|
||||||
|
modifier = modifier.then(pressIndicator),
|
||||||
|
style = style,
|
||||||
|
softWrap = softWrap,
|
||||||
|
overflow = overflow,
|
||||||
|
maxLines = maxLines,
|
||||||
|
onTextLayout = {
|
||||||
|
layoutResult.value = it
|
||||||
|
onTextLayout(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
@@ -47,7 +48,8 @@ fun FavouriteListPage() {
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.weight(1f).pullRefresh(state)
|
.weight(1f)
|
||||||
|
.pullRefresh(state)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
@@ -57,7 +59,7 @@ fun FavouriteListPage() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||||
) {
|
) {
|
||||||
NoticeScreenHeader("Favourite")
|
NoticeScreenHeader(stringResource(R.string.favourites_upper), moreIcon = false)
|
||||||
}
|
}
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(3),
|
||||||
|
|||||||
@@ -20,11 +20,8 @@ import androidx.compose.foundation.pager.rememberPagerState
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.CircularProgressIndicator
|
import androidx.compose.material.CircularProgressIndicator
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.ModalBottomSheetValue
|
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -35,30 +32,28 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
|
||||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.LocalSharedTransitionScope
|
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.ui.composables.CustomAsyncImage
|
import com.aiosman.riderpro.ui.composables.CustomAsyncImage
|
||||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||||
import com.aiosman.riderpro.ui.imageviewer.ImageViewerViewModel
|
import com.aiosman.riderpro.ui.imageviewer.ImageViewerViewModel
|
||||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
import com.aiosman.riderpro.utils.File.saveImageToGallery
|
import com.aiosman.riderpro.utils.File.saveImageToGallery
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.engawapg.lib.zoomable.rememberZoomState
|
import net.engawapg.lib.zoomable.rememberZoomState
|
||||||
import net.engawapg.lib.zoomable.zoomable
|
import net.engawapg.lib.zoomable.zoomable
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class,
|
@OptIn(
|
||||||
ExperimentalMaterial3Api::class
|
ExperimentalFoundationApi::class,
|
||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageViewer() {
|
fun ImageViewer() {
|
||||||
@@ -72,8 +67,11 @@ fun ImageViewer() {
|
|||||||
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 16.dp
|
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 16.dp
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val showRawImageStates = remember { mutableStateListOf(*Array(images.size) { false }) }
|
val showRawImageStates = remember { mutableStateListOf(*Array(images.size) { false }) }
|
||||||
var showBottomSheet by remember { mutableStateOf(false) }
|
|
||||||
var isDownloading by remember { mutableStateOf(false) }
|
var isDownloading by remember { mutableStateOf(false) }
|
||||||
|
var currentPage by remember { mutableStateOf(model.initialIndex) }
|
||||||
|
LaunchedEffect(pagerState) {
|
||||||
|
currentPage = pagerState.currentPage
|
||||||
|
}
|
||||||
StatusBarMaskLayout(
|
StatusBarMaskLayout(
|
||||||
modifier = Modifier.background(Color.Black),
|
modifier = Modifier.background(Color.Black),
|
||||||
) {
|
) {
|
||||||
@@ -84,7 +82,7 @@ fun ImageViewer() {
|
|||||||
) {
|
) {
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize(),
|
||||||
) { page ->
|
) { page ->
|
||||||
val zoomState = rememberZoomState()
|
val zoomState = rememberZoomState()
|
||||||
CustomAsyncImage(
|
CustomAsyncImage(
|
||||||
@@ -102,6 +100,23 @@ fun ImageViewer() {
|
|||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (images.size > 1) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(Color(0xff333333).copy(alpha = 0.6f))
|
||||||
|
.padding(vertical = 4.dp, horizontal = 24.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "${pagerState.currentPage + 1}/${images.size}",
|
||||||
|
color = Color.White,
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -142,7 +157,7 @@ fun ImageViewer() {
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
}else{
|
} else {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_download),
|
painter = painterResource(id = R.drawable.rider_pro_download),
|
||||||
contentDescription = "",
|
contentDescription = "",
|
||||||
@@ -153,7 +168,7 @@ fun ImageViewer() {
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
"Download",
|
stringResource(R.string.download),
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -174,7 +189,7 @@ fun ImageViewer() {
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
"Original",
|
stringResource(R.string.original),
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.LinearProgressIndicator
|
||||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
@@ -43,6 +44,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.LoadState
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
@@ -81,10 +83,12 @@ fun NotificationsScreen() {
|
|||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
StatusBarSpacer()
|
StatusBarSpacer()
|
||||||
Box(modifier = Modifier
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.pullRefresh(state)) {
|
.pullRefresh(state)
|
||||||
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
@@ -118,6 +122,31 @@ fun NotificationsScreen() {
|
|||||||
}
|
}
|
||||||
HorizontalDivider(color = Color(0xFFEbEbEb), modifier = Modifier.padding(16.dp))
|
HorizontalDivider(color = Color(0xFFEbEbEb), modifier = Modifier.padding(16.dp))
|
||||||
NotificationCounterItem(MessageListViewModel.commentNoticeCount)
|
NotificationCounterItem(MessageListViewModel.commentNoticeCount)
|
||||||
|
if (comments.loadState.refresh is LoadState.Loading) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 48.dp)
|
||||||
|
,
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Loading",
|
||||||
|
fontSize = 18.sp
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.width(160.dp),
|
||||||
|
color = Color(0xFFDA3832)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@@ -128,8 +157,6 @@ fun NotificationsScreen() {
|
|||||||
CommentNoticeItem(comment) {
|
CommentNoticeItem(comment) {
|
||||||
MessageListViewModel.updateReadStatus(comment.id)
|
MessageListViewModel.updateReadStatus(comment.id)
|
||||||
MessageListViewModel.viewModelScope.launch {
|
MessageListViewModel.viewModelScope.launch {
|
||||||
// PostViewModel.postId = comment.postId.toString()
|
|
||||||
// PostViewModel.initData()
|
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
NavigationRoute.Post.route.replace(
|
NavigationRoute.Post.route.replace(
|
||||||
"{id}",
|
"{id}",
|
||||||
@@ -137,7 +164,43 @@ fun NotificationsScreen() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle load error
|
||||||
|
when {
|
||||||
|
comments.loadState.append is LoadState.Loading -> {
|
||||||
|
item {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(64.dp)
|
||||||
|
.padding(16.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.width(160.dp),
|
||||||
|
color = Color(0xFFDA3832)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comments.loadState.append is LoadState.Error -> {
|
||||||
|
item {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(64.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
comments.retry()
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Load comment error, click to retry",
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,6 +209,7 @@ fun NotificationsScreen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PullRefreshIndicator(
|
PullRefreshIndicator(
|
||||||
MessageListViewModel.isLoading,
|
MessageListViewModel.isLoading,
|
||||||
state,
|
state,
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
profile = accountService.getMyAccountProfile()
|
profile = accountService.getMyAccountProfile()
|
||||||
val profile = accountService.getMyAccountProfile()
|
val profile = accountService.getMyAccountProfile()
|
||||||
refreshing = false
|
refreshing = false
|
||||||
|
try {
|
||||||
Pager(
|
Pager(
|
||||||
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
pagingSourceFactory = {
|
pagingSourceFactory = {
|
||||||
@@ -56,6 +57,10 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
).flow.cachedIn(viewModelScope).collectLatest {
|
).flow.cachedIn(viewModelScope).collectLatest {
|
||||||
_momentsFlow.value = it
|
_momentsFlow.value = it
|
||||||
}
|
}
|
||||||
|
}catch (e: Exception){
|
||||||
|
Log.e("MyProfileViewModel", "loadProfile: ", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,8 +162,6 @@ fun ProfilePage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.TopEnd)
|
.align(Alignment.TopEnd)
|
||||||
@@ -174,10 +172,14 @@ fun ProfilePage() {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(16.dp).clip(RoundedCornerShape(8.dp)).shadow(
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.shadow(
|
||||||
elevation = 20.dp
|
elevation = 20.dp
|
||||||
).background(Color.White.copy(alpha = 0.7f))
|
)
|
||||||
){
|
.background(Color.White.copy(alpha = 0.7f))
|
||||||
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
|
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
|
||||||
contentDescription = "",
|
contentDescription = "",
|
||||||
@@ -191,7 +193,7 @@ fun ProfilePage() {
|
|||||||
com.aiosman.riderpro.ui.composables.DropdownMenu(
|
com.aiosman.riderpro.ui.composables.DropdownMenu(
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
onDismissRequest = { expanded = false },
|
onDismissRequest = { expanded = false },
|
||||||
width = 300,
|
width = 250,
|
||||||
menuItems = listOf(
|
menuItems = listOf(
|
||||||
MenuItem(
|
MenuItem(
|
||||||
stringResource(R.string.logout),
|
stringResource(R.string.logout),
|
||||||
@@ -217,7 +219,7 @@ fun ProfilePage() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
MenuItem(
|
MenuItem(
|
||||||
"Favourite",
|
stringResource(R.string.favourites),
|
||||||
R.drawable.rider_pro_favourite
|
R.drawable.rider_pro_favourite
|
||||||
) {
|
) {
|
||||||
expanded = false
|
expanded = false
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class CommentsViewModel(
|
|||||||
|
|
||||||
fun reloadComment() {
|
fun reloadComment() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
Pager(config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
Pager(config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
pagingSourceFactory = {
|
pagingSourceFactory = {
|
||||||
CommentPagingSource(
|
CommentPagingSource(
|
||||||
@@ -59,6 +60,9 @@ class CommentsViewModel(
|
|||||||
}).flow.cachedIn(viewModelScope).collectLatest {
|
}).flow.cachedIn(viewModelScope).collectLatest {
|
||||||
_commentsFlow.value = it
|
_commentsFlow.value = it
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,9 +148,14 @@ class CommentsViewModel(
|
|||||||
fun deleteComment(commentId: Int) {
|
fun deleteComment(commentId: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
commentService.DeleteComment(commentId)
|
commentService.DeleteComment(commentId)
|
||||||
|
// 如果是刚刚创建的评论,则从addedCommentList中删除
|
||||||
|
if (addedCommentList.any { it.id == commentId }) {
|
||||||
|
addedCommentList = addedCommentList.filter { it.id != commentId }
|
||||||
|
} else {
|
||||||
reloadComment()
|
reloadComment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun loadMoreSubComments(commentId: Int) {
|
fun loadMoreSubComments(commentId: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.aiosman.riderpro.ui.post
|
package com.aiosman.riderpro.ui.post
|
||||||
|
|
||||||
import android.util.Log
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.slideInVertically
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@@ -14,7 +16,6 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
@@ -24,17 +25,12 @@ import androidx.compose.foundation.layout.width
|
|||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.ClickableText
|
import androidx.compose.foundation.text.ClickableText
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Delete
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -46,22 +42,24 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.snapshotFlow
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.text.withStyle
|
import androidx.compose.ui.text.withStyle
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -69,7 +67,6 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.paging.compose.LazyPagingItems
|
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.aiosman.riderpro.AppState
|
import com.aiosman.riderpro.AppState
|
||||||
import com.aiosman.riderpro.LocalAnimatedContentScope
|
import com.aiosman.riderpro.LocalAnimatedContentScope
|
||||||
@@ -82,7 +79,6 @@ import com.aiosman.riderpro.entity.MomentImageEntity
|
|||||||
import com.aiosman.riderpro.exp.formatPostTime
|
import com.aiosman.riderpro.exp.formatPostTime
|
||||||
import com.aiosman.riderpro.exp.timeAgo
|
import com.aiosman.riderpro.exp.timeAgo
|
||||||
import com.aiosman.riderpro.ui.NavigationRoute
|
import com.aiosman.riderpro.ui.NavigationRoute
|
||||||
import com.aiosman.riderpro.ui.comment.CommentModalViewModel
|
|
||||||
import com.aiosman.riderpro.ui.composables.AnimatedFavouriteIcon
|
import com.aiosman.riderpro.ui.composables.AnimatedFavouriteIcon
|
||||||
import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon
|
import com.aiosman.riderpro.ui.composables.AnimatedLikeIcon
|
||||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||||
@@ -92,6 +88,13 @@ import com.aiosman.riderpro.ui.composables.StatusBarSpacer
|
|||||||
import com.aiosman.riderpro.ui.imageviewer.ImageViewerViewModel
|
import com.aiosman.riderpro.ui.imageviewer.ImageViewerViewModel
|
||||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
|
import androidx.compose.material.LinearProgressIndicator
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.paging.LoadState
|
||||||
|
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
|
||||||
|
import com.aiosman.riderpro.ui.composables.CustomClickableText
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -113,28 +116,67 @@ fun PostScreen(
|
|||||||
var contextComment by remember { mutableStateOf<CommentEntity?>(null) }
|
var contextComment by remember { mutableStateOf<CommentEntity?>(null) }
|
||||||
var replyComment by remember { mutableStateOf<CommentEntity?>(null) }
|
var replyComment by remember { mutableStateOf<CommentEntity?>(null) }
|
||||||
var showCommentModal by remember { mutableStateOf(false) }
|
var showCommentModal by remember { mutableStateOf(false) }
|
||||||
|
var commentModalState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||||
|
var editCommentModalState = rememberModalBottomSheetState(
|
||||||
|
skipPartiallyExpanded = true
|
||||||
|
)
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.initData()
|
viewModel.initData()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showCommentMenu) {
|
if (showCommentMenu) {
|
||||||
ModalBottomSheet(
|
ModalBottomSheet(
|
||||||
onDismissRequest = {
|
onDismissRequest = {
|
||||||
showCommentMenu = false
|
showCommentMenu = false
|
||||||
},
|
},
|
||||||
containerColor = Color.White,
|
containerColor = Color.White,
|
||||||
sheetState = rememberModalBottomSheetState(
|
sheetState = commentModalState,
|
||||||
skipPartiallyExpanded = true
|
|
||||||
),
|
|
||||||
dragHandle = {},
|
dragHandle = {},
|
||||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||||
windowInsets = WindowInsets(0)
|
windowInsets = WindowInsets(0)
|
||||||
) {
|
) {
|
||||||
CommentMenuModal(
|
CommentMenuModal(
|
||||||
onDeleteClick = {
|
onDeleteClick = {
|
||||||
|
scope.launch {
|
||||||
|
commentModalState.hide()
|
||||||
showCommentMenu = false
|
showCommentMenu = false
|
||||||
|
}
|
||||||
contextComment?.let {
|
contextComment?.let {
|
||||||
viewModel.deleteComment(it.id)
|
viewModel.deleteComment(it.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
commentEntity = contextComment,
|
||||||
|
onCloseClick = {
|
||||||
|
scope.launch {
|
||||||
|
commentModalState.hide()
|
||||||
|
showCommentMenu = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSelf = AppState.UserId?.toLong() == contextComment?.author,
|
||||||
|
onLikeClick = {
|
||||||
|
scope.launch {
|
||||||
|
commentModalState.hide()
|
||||||
|
showCommentMenu = false
|
||||||
|
}
|
||||||
|
contextComment?.let {
|
||||||
|
viewModel.viewModelScope.launch {
|
||||||
|
if (it.liked) {
|
||||||
|
viewModel.unlikeComment(it.id)
|
||||||
|
} else {
|
||||||
|
viewModel.likeComment(it.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
onReplyClick = {
|
||||||
|
scope.launch {
|
||||||
|
commentModalState.hide()
|
||||||
|
showCommentMenu = false
|
||||||
|
replyComment = contextComment
|
||||||
|
showCommentModal = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -177,6 +219,8 @@ fun PostScreen(
|
|||||||
content = it
|
content = it
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editCommentModalState.hide()
|
||||||
showCommentModal = false
|
showCommentModal = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +230,7 @@ fun PostScreen(
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
|
if (!viewModel.isError) {
|
||||||
PostBottomBar(
|
PostBottomBar(
|
||||||
onLikeClick = {
|
onLikeClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -212,6 +257,8 @@ fun PostScreen(
|
|||||||
momentEntity = viewModel.moment
|
momentEntity = viewModel.moment
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
it
|
it
|
||||||
Column(
|
Column(
|
||||||
@@ -220,14 +267,35 @@ fun PostScreen(
|
|||||||
.background(Color.White)
|
.background(Color.White)
|
||||||
) {
|
) {
|
||||||
StatusBarSpacer()
|
StatusBarSpacer()
|
||||||
|
if (viewModel.isError) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(16.dp)
|
||||||
|
) {
|
||||||
|
NoticeScreenHeader("Post", moreIcon = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Umm, post are not found.",
|
||||||
|
style = TextStyle(
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}else{
|
||||||
Header(
|
Header(
|
||||||
avatar = viewModel.avatar,
|
avatar = viewModel.avatar,
|
||||||
nickname = viewModel.nickname,
|
nickname = viewModel.nickname,
|
||||||
userId = viewModel.moment?.authorId,
|
userId = viewModel.moment?.authorId,
|
||||||
isFollowing = viewModel.accountProfileEntity?.isFollowing ?: false,
|
isFollowing = viewModel.moment?.followStatus == true,
|
||||||
onFollowClick = {
|
onFollowClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
if (viewModel.accountProfileEntity?.isFollowing == true) {
|
if (viewModel.moment?.followStatus == true) {
|
||||||
viewModel.unfollowUser()
|
viewModel.unfollowUser()
|
||||||
} else {
|
} else {
|
||||||
viewModel.followUser()
|
viewModel.followUser()
|
||||||
@@ -295,9 +363,9 @@ fun PostScreen(
|
|||||||
item {
|
item {
|
||||||
CommentContent(
|
CommentContent(
|
||||||
viewModel = commentsViewModel,
|
viewModel = commentsViewModel,
|
||||||
onLongClick = {
|
onLongClick = { comment ->
|
||||||
showCommentMenu = true
|
showCommentMenu = true
|
||||||
contextComment = it
|
contextComment = comment
|
||||||
},
|
},
|
||||||
onReply = { parentComment, _, _, _ ->
|
onReply = { parentComment, _, _, _ ->
|
||||||
replyComment = parentComment
|
replyComment = parentComment
|
||||||
@@ -311,6 +379,8 @@ fun PostScreen(
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -327,6 +397,10 @@ fun CommentContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (item in addedTopLevelComment) {
|
for (item in addedTopLevelComment) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = true,
|
||||||
|
enter = fadeIn() + slideInVertically()
|
||||||
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp)
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
@@ -341,11 +415,8 @@ fun CommentContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClick = {
|
onLongClick = { comment ->
|
||||||
if (AppState.UserId != item.id) {
|
onLongClick(comment)
|
||||||
return@CommentItem
|
|
||||||
}
|
|
||||||
onLongClick(item)
|
|
||||||
},
|
},
|
||||||
onReply = { parentComment, _, _, _ ->
|
onReply = { parentComment, _, _, _ ->
|
||||||
onReply(
|
onReply(
|
||||||
@@ -364,6 +435,7 @@ fun CommentContent(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (idx in 0 until commentsPagging.itemCount) {
|
for (idx in 0 until commentsPagging.itemCount) {
|
||||||
val item = commentsPagging[idx] ?: return
|
val item = commentsPagging[idx] ?: return
|
||||||
@@ -381,11 +453,8 @@ fun CommentContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClick = {
|
onLongClick = { comment ->
|
||||||
if (AppState.UserId != item.id) {
|
onLongClick(comment)
|
||||||
return@CommentItem
|
|
||||||
}
|
|
||||||
onLongClick(item)
|
|
||||||
},
|
},
|
||||||
onReply = { parentComment, _, _, _ ->
|
onReply = { parentComment, _, _, _ ->
|
||||||
onReply(
|
onReply(
|
||||||
@@ -404,6 +473,67 @@ fun CommentContent(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (commentsPagging.loadState.refresh is LoadState.Loading) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize().height(120.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.width(160.dp),
|
||||||
|
color = Color(0xFFDA3832)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "Loading...",
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (commentsPagging.loadState.append is LoadState.Loading) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize().height(64.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.width(160.dp),
|
||||||
|
color = Color(0xFFDA3832)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (commentsPagging.loadState.refresh is LoadState.Error) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize().height(120.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Failed to load comments,click to retry",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier.noRippleClickable {
|
||||||
|
viewModel.reloadComment()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (commentsPagging.loadState.append is LoadState.Error) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize().height(64.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Failed to load more comments,click to retry",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier.noRippleClickable {
|
||||||
|
commentsPagging.retry()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -499,9 +629,10 @@ fun Header(
|
|||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.height(18.dp),
|
modifier = Modifier.height(18.dp).width(80.dp),
|
||||||
painter = painterResource(id = R.drawable.follow_bg),
|
painter = painterResource(id = R.drawable.follow_bg),
|
||||||
contentDescription = ""
|
contentDescription = "",
|
||||||
|
contentScale = ContentScale.FillWidth
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = if (isFollowing) stringResource(R.string.following_upper) else stringResource(
|
text = if (isFollowing) stringResource(R.string.following_upper) else stringResource(
|
||||||
@@ -581,7 +712,7 @@ fun PostImageView(
|
|||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
if(images.size > 1){
|
if (images.size > 1) {
|
||||||
images.forEachIndexed { index, _ ->
|
images.forEachIndexed { index, _ ->
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -626,47 +757,28 @@ fun PostDetails(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentsSection(
|
fun LongPressClickableText(
|
||||||
lazyPagingItems: LazyPagingItems<CommentEntity>,
|
text: AnnotatedString,
|
||||||
scrollState: LazyListState = rememberLazyListState(),
|
onClick: (Int) -> Unit,
|
||||||
onLike: (CommentEntity) -> Unit,
|
onLongClick: () -> Unit,
|
||||||
onLongClick: (CommentEntity) -> Unit,
|
style: TextStyle = TextStyle.Default
|
||||||
onWillCollapse: (Boolean) -> Unit,
|
|
||||||
) {
|
) {
|
||||||
LazyColumn(
|
ClickableText(
|
||||||
state = scrollState, modifier = Modifier
|
text = text,
|
||||||
.fillMaxHeight()
|
onClick = onClick,
|
||||||
.padding(start = 16.dp, end = 16.dp)
|
style = style,
|
||||||
) {
|
modifier = Modifier.pointerInput(Unit) {
|
||||||
items(lazyPagingItems.itemCount) { idx ->
|
detectTapGestures(
|
||||||
val item = lazyPagingItems[idx] ?: return@items
|
onLongPress = {
|
||||||
CommentItem(
|
onLongClick()
|
||||||
item,
|
|
||||||
onLike = {
|
|
||||||
onLike(item)
|
|
||||||
},
|
},
|
||||||
onLongClick = {
|
|
||||||
onLongClick(item)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
|
|
||||||
// Detect scroll direction and update showCollapseContent
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
LaunchedEffect(scrollState) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
snapshotFlow { scrollState.firstVisibleItemScrollOffset }
|
|
||||||
.collect { offset ->
|
|
||||||
Log.d("scroll", "offset: $offset")
|
|
||||||
onWillCollapse(offset == 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentItem(
|
fun CommentItem(
|
||||||
@@ -680,7 +792,7 @@ fun CommentItem(
|
|||||||
replyUserAvatar: String?
|
replyUserAvatar: String?
|
||||||
) -> Unit = { _, _, _, _ -> },
|
) -> Unit = { _, _, _, _ -> },
|
||||||
onLoadMoreSubComments: ((CommentEntity) -> Unit)? = {},
|
onLoadMoreSubComments: ((CommentEntity) -> Unit)? = {},
|
||||||
onLongClick: () -> Unit = {},
|
onLongClick: (CommentEntity) -> Unit = {},
|
||||||
addedCommentList: List<CommentEntity> = emptyList()
|
addedCommentList: List<CommentEntity> = emptyList()
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
@@ -688,12 +800,6 @@ fun CommentItem(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.combinedClickable(
|
|
||||||
indication = null,
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
onClick = {},
|
|
||||||
onLongClick = onLongClick
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
Row(modifier = Modifier.padding(vertical = 8.dp)) {
|
Row(modifier = Modifier.padding(vertical = 8.dp)) {
|
||||||
Box(
|
Box(
|
||||||
@@ -719,7 +825,15 @@ fun CommentItem(
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.combinedClickable(
|
||||||
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
indication = null,
|
||||||
|
onLongClick = {
|
||||||
|
onLongClick(commentEntity)
|
||||||
|
}
|
||||||
|
) {}
|
||||||
) {
|
) {
|
||||||
Text(text = commentEntity.name, fontWeight = FontWeight.W600, fontSize = 14.sp)
|
Text(text = commentEntity.name, fontWeight = FontWeight.W600, fontSize = 14.sp)
|
||||||
Row {
|
Row {
|
||||||
@@ -741,8 +855,10 @@ fun CommentItem(
|
|||||||
pop()
|
pop()
|
||||||
}
|
}
|
||||||
append(" ${commentEntity.comment}")
|
append(" ${commentEntity.comment}")
|
||||||
|
|
||||||
}
|
}
|
||||||
ClickableText(
|
Box {
|
||||||
|
CustomClickableText(
|
||||||
text = annotatedText,
|
text = annotatedText,
|
||||||
onClick = { offset ->
|
onClick = { offset ->
|
||||||
annotatedText.getStringAnnotations(
|
annotatedText.getStringAnnotations(
|
||||||
@@ -759,15 +875,29 @@ fun CommentItem(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
style = TextStyle(fontSize = 14.sp),
|
style = TextStyle(fontSize = 14.sp),
|
||||||
maxLines = Int.MAX_VALUE,
|
onLongPress = {
|
||||||
softWrap = true
|
onLongClick(commentEntity)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Text(
|
Text(
|
||||||
text = commentEntity.comment,
|
text = commentEntity.comment,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
maxLines = Int.MAX_VALUE,
|
maxLines = Int.MAX_VALUE,
|
||||||
softWrap = true
|
softWrap = true,
|
||||||
|
modifier = Modifier.combinedClickable(
|
||||||
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
|
indication = null,
|
||||||
|
onLongClick = {
|
||||||
|
onLongClick(
|
||||||
|
commentEntity
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -832,7 +962,9 @@ fun CommentItem(
|
|||||||
isChild = true,
|
isChild = true,
|
||||||
onLike = onLike,
|
onLike = onLike,
|
||||||
onReply = onReply,
|
onReply = onReply,
|
||||||
onLongClick = onLongClick
|
onLongClick = { comment ->
|
||||||
|
onLongClick(comment)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (commentEntity.replyCount > 0 && !isChild && commentEntity.reply.size < commentEntity.replyCount) {
|
if (commentEntity.replyCount > 0 && !isChild && commentEntity.reply.size < commentEntity.replyCount) {
|
||||||
@@ -851,7 +983,6 @@ fun CommentItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PostBottomBar(
|
fun PostBottomBar(
|
||||||
onCreateCommentClick: () -> Unit = {},
|
onCreateCommentClick: () -> Unit = {},
|
||||||
@@ -956,12 +1087,16 @@ fun PostMenuModal(
|
|||||||
onDeleteClick()
|
onDeleteClick()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Image(painter = painterResource(id = R.drawable.rider_pro_moment_delete), contentDescription = "",modifier = Modifier.size(24.dp))
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_moment_delete),
|
||||||
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Delete",
|
text = stringResource(R.string.delete),
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
@@ -971,20 +1106,12 @@ fun PostMenuModal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentMenuModal(
|
fun MenuActionItem(
|
||||||
onDeleteClick: () -> Unit = {}
|
icon: Int? = null,
|
||||||
|
text: String,
|
||||||
|
content: @Composable() (() -> Unit)? = null,
|
||||||
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(160.dp)
|
|
||||||
.padding(vertical = 47.dp, horizontal = 20.dp)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth(),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
@@ -994,21 +1121,151 @@ fun CommentMenuModal(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
onDeleteClick()
|
onClick()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Image(painter = painterResource(id = R.drawable.rider_pro_moment_delete), contentDescription = "",modifier = Modifier.size(24.dp))
|
content?.invoke()
|
||||||
|
if (icon != null) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = icon),
|
||||||
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
tint = Color.Black
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Delete",
|
text = text,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 评论菜单弹窗
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun CommentMenuModal(
|
||||||
|
onDeleteClick: () -> Unit = {},
|
||||||
|
commentEntity: CommentEntity? = null,
|
||||||
|
onCloseClick: () -> Unit = {},
|
||||||
|
onLikeClick: () -> Unit = {},
|
||||||
|
onReplyClick: () -> Unit = {},
|
||||||
|
isSelf: Boolean = false
|
||||||
|
) {
|
||||||
|
val clipboard = LocalClipboardManager.current
|
||||||
|
|
||||||
|
fun copyToClipboard() {
|
||||||
|
commentEntity?.let {
|
||||||
|
clipboard.setText(
|
||||||
|
AnnotatedString(
|
||||||
|
text = it.comment,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 24.dp, horizontal = 20.dp)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.comment), fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
commentEntity?.let {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0xffeeeeee))
|
||||||
|
|
||||||
|
.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(24.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
) {
|
||||||
|
CustomAsyncImage(
|
||||||
|
imageUrl = it.avatar,
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentDescription = "Avatar",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
androidx.compose.material.Text(
|
||||||
|
it.name,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
androidx.compose.material.Text(
|
||||||
|
it.comment,
|
||||||
|
maxLines = 1,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 32.dp),
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
if (isSelf) {
|
||||||
|
MenuActionItem(
|
||||||
|
icon = R.drawable.rider_pro_moment_delete,
|
||||||
|
text = stringResource(R.string.delete)
|
||||||
|
) {
|
||||||
|
onDeleteClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(48.dp))
|
||||||
|
}
|
||||||
|
MenuActionItem(
|
||||||
|
icon = R.drawable.rider_pro_copy,
|
||||||
|
text = stringResource(R.string.copy)
|
||||||
|
) {
|
||||||
|
copyToClipboard()
|
||||||
|
onCloseClick()
|
||||||
|
}
|
||||||
|
commentEntity?.let {
|
||||||
|
Spacer(modifier = Modifier.width(48.dp))
|
||||||
|
MenuActionItem(
|
||||||
|
text = "Like",
|
||||||
|
content = {
|
||||||
|
AnimatedLikeIcon(
|
||||||
|
liked = it.liked,
|
||||||
|
onClick = onLikeClick,
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
onCloseClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isSelf) {
|
||||||
|
Spacer(modifier = Modifier.width(48.dp))
|
||||||
|
MenuActionItem(
|
||||||
|
icon = R.drawable.rider_pro_comment,
|
||||||
|
text = "Reply"
|
||||||
|
) {
|
||||||
|
onReplyClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(48.dp))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -28,24 +28,20 @@ class PostViewModel(
|
|||||||
var moment by mutableStateOf<MomentEntity?>(null)
|
var moment by mutableStateOf<MomentEntity?>(null)
|
||||||
var accountService: AccountService = AccountServiceImpl()
|
var accountService: AccountService = AccountServiceImpl()
|
||||||
var commentsViewModel: CommentsViewModel = CommentsViewModel(postId)
|
var commentsViewModel: CommentsViewModel = CommentsViewModel(postId)
|
||||||
|
var isError by mutableStateOf(false)
|
||||||
|
|
||||||
/**
|
|
||||||
* 预加载,在跳转到 PostScreen 之前设置好内容
|
|
||||||
*/
|
|
||||||
fun preTransit(momentEntity: MomentEntity?) {
|
|
||||||
this.moment = momentEntity
|
|
||||||
this.nickname = momentEntity?.nickname ?: ""
|
|
||||||
this.commentsViewModel = CommentsViewModel(postId)
|
|
||||||
commentsViewModel.preTransit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reloadComment() {
|
fun reloadComment() {
|
||||||
commentsViewModel.reloadComment()
|
commentsViewModel.reloadComment()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun initData() {
|
suspend fun initData() {
|
||||||
|
try {
|
||||||
moment = service.getMomentById(postId.toInt())
|
moment = service.getMomentById(postId.toInt())
|
||||||
// accountProfileEntity = userService.getUserProfile(moment?.authorId.toString())
|
} catch (e: Exception) {
|
||||||
|
isError = true
|
||||||
|
return
|
||||||
|
}
|
||||||
commentsViewModel.reloadComment()
|
commentsViewModel.reloadComment()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,16 +102,16 @@ class PostViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun followUser() {
|
suspend fun followUser() {
|
||||||
accountProfileEntity?.let {
|
moment?.let {
|
||||||
userService.followUser(it.id.toString())
|
userService.followUser(it.authorId.toString())
|
||||||
accountProfileEntity = accountProfileEntity?.copy(isFollowing = true)
|
moment = moment?.copy(followStatus = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun unfollowUser() {
|
suspend fun unfollowUser() {
|
||||||
accountProfileEntity?.let {
|
moment?.let {
|
||||||
userService.unFollowUser(it.id.toString())
|
userService.unFollowUser(it.authorId.toString())
|
||||||
accountProfileEntity = accountProfileEntity?.copy(isFollowing = false)
|
moment = moment?.copy(followStatus = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
app/src/main/res/drawable/rider_pro_copy.xml
Normal file
5
app/src/main/res/drawable/rider_pro_copy.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:alpha="0.77" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M15,20H5V7c0,-0.55 -0.45,-1 -1,-1h0C3.45,6 3,6.45 3,7v13c0,1.1 0.9,2 2,2h10c0.55,0 1,-0.45 1,-1v0C16,20.45 15.55,20 15,20zM20,16V4c0,-1.1 -0.9,-2 -2,-2H9C7.9,2 7,2.9 7,4v12c0,1.1 0.9,2 2,2h9C19.1,18 20,17.1 20,16zM18,16H9V4h9V16z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -57,4 +57,8 @@
|
|||||||
<string name="order_comment_default">默认</string>
|
<string name="order_comment_default">默认</string>
|
||||||
<string name="order_comment_latest">最新</string>
|
<string name="order_comment_latest">最新</string>
|
||||||
<string name="order_comment_earliest">最早</string>
|
<string name="order_comment_earliest">最早</string>
|
||||||
|
<string name="download">下载</string>
|
||||||
|
<string name="original">原始图片</string>
|
||||||
|
<string name="favourites">收藏</string>
|
||||||
|
<string name="delete">删除</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -56,4 +56,9 @@
|
|||||||
<string name="order_comment_default">Default</string>
|
<string name="order_comment_default">Default</string>
|
||||||
<string name="order_comment_latest">Latest</string>
|
<string name="order_comment_latest">Latest</string>
|
||||||
<string name="order_comment_earliest">Earliest</string>
|
<string name="order_comment_earliest">Earliest</string>
|
||||||
|
<string name="download">Download</string>
|
||||||
|
<string name="original">Original</string>
|
||||||
|
<string name="favourites">Favourite</string>
|
||||||
|
<string name="delete">Delete</string>
|
||||||
|
<string name="copy">Copy</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user