This commit is contained in:
2024-10-08 17:25:27 +08:00
parent dcdd42d6b0
commit 43c27b7e0b
11 changed files with 134 additions and 26 deletions

View File

@@ -6,8 +6,6 @@ import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.icu.util.Calendar
import android.icu.util.TimeZone
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -32,12 +30,7 @@ import com.aiosman.riderpro.ui.Navigation
import com.aiosman.riderpro.ui.NavigationRoute
import com.aiosman.riderpro.ui.navigateToPost
import com.aiosman.riderpro.ui.post.NewPostViewModel
import com.aiosman.riderpro.utils.Utils
import com.google.firebase.analytics.FirebaseAnalytics
import com.tencent.imsdk.v2.V2TIMCallback
import com.tencent.imsdk.v2.V2TIMLogListener
import com.tencent.imsdk.v2.V2TIMManager
import com.tencent.imsdk.v2.V2TIMSDKConfig
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

View File

@@ -105,6 +105,9 @@ data class NoticePost(
it.copy(
url = "${ApiClient.BASE_SERVER}${it.url}",
thumbnail = "${ApiClient.BASE_SERVER}${it.thumbnail}",
blurHash = it.blurHash,
width = it.width,
height = it.height
)
},
time = ApiClient.dateFromApiString(time)

View File

@@ -52,12 +52,14 @@ data class Moment(
url = "${ApiClient.BASE_SERVER}${it.url}",
thumbnail = "${ApiClient.BASE_SERVER}${it.thumbnail}",
id = it.id,
blurHash = it.blurHash
blurHash = it.blurHash,
width = it.width,
height = it.height
)
},
authorId = user.id.toInt(),
liked = isLiked,
isFavorite = isFavorite
isFavorite = isFavorite,
)
}
}
@@ -70,7 +72,11 @@ data class Image(
@SerializedName("thumbnail")
val thumbnail: String,
@SerializedName("blurHash")
val blurHash: String?
val blurHash: String?,
@SerializedName("width")
val width: Int?,
@SerializedName("height")
val height: Int?
)
data class User(

View File

@@ -230,7 +230,11 @@ data class MomentImageEntity(
// 缩略图URL
val thumbnail: String,
// 图片BlurHash
val blurHash: String? = null
val blurHash: String? = null,
// 宽度
var width: Int? = null,
// 高度
var height: Int? = null
)
/**

View File

@@ -501,7 +501,6 @@ fun ProfileV3(
Spacer(modifier = Modifier.height(120.dp))
}
}
1 ->
LazyColumn(
modifier = Modifier

View File

@@ -21,15 +21,25 @@ import com.aiosman.riderpro.ui.navigateToPost
fun GalleryItem(
moment: MomentEntity,
idx: Int = 0
){
) {
val navController = LocalNavController.current
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(
if (idx % 3 == 0) 1.5f else 1f
)
.let {
val firstImage = moment.images.firstOrNull()
if (firstImage?.width != null &&
firstImage.height != null &&
firstImage.width!! > 0 &&
firstImage.height!! > 0
) {
val ratio = firstImage.width!!.toFloat() / firstImage.height!!.toFloat()
return@let it.aspectRatio(ratio.coerceIn(0.7f, 1.5f))
} else {
return@let it.aspectRatio(if (idx % 3 == 0) 1.5f else 1f)
}
}
.clip(RoundedCornerShape(8.dp))
.noRippleClickable {
navController.navigateToPost(

View File

@@ -1,6 +1,5 @@
package com.aiosman.riderpro.ui.index.tabs.search
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
@@ -50,7 +49,7 @@ import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import com.aiosman.riderpro.ui.navigateToPost
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)
@OptIn( ExperimentalMaterialApi::class)
@Preview
@Composable
fun DiscoverScreen() {
@@ -82,6 +81,7 @@ fun DiscoverScreen() {
.fillMaxWidth()
.padding(top = 16.dp, start = 24.dp, end = 24.dp),
) {
SearchViewModel.requestFocus = true
navController.navigate(NavigationRoute.Search.route)
}
}
@@ -150,7 +150,6 @@ fun DiscoverView() {
.fillMaxWidth()
.aspectRatio(1f)
.padding(2.dp)
.noRippleClickable {
navController.navigateToPost(
id = momentItem.id,

View File

@@ -4,6 +4,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
@@ -51,9 +52,11 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.riderpro.AppState
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R
import com.aiosman.riderpro.entity.AccountProfileEntity
import com.aiosman.riderpro.ui.composables.ActionButton
import com.aiosman.riderpro.ui.composables.CustomAsyncImage
import com.aiosman.riderpro.ui.index.tabs.moment.MomentCard
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
@@ -82,7 +85,10 @@ fun SearchScreen() {
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
}
LaunchedEffect(Unit) {
if (model.requestFocus) {
focusRequester.requestFocus()
model.requestFocus = false
}
}
Column(
@@ -246,7 +252,8 @@ fun MomentResultTab() {
val momentItem = moments[idx] ?: return@items
Box(
modifier = Modifier
.fillMaxWidth().background(Color.White)
.fillMaxWidth()
.background(Color.White)
) {
MomentCard(momentEntity = momentItem, hideAction = true)
}
@@ -260,6 +267,7 @@ fun MomentResultTab() {
fun UserResultTab() {
val model = SearchViewModel
val users = model.usersFlow.collectAsLazyPagingItems()
val scope = rememberCoroutineScope()
Box(
modifier = Modifier.fillMaxSize()
) {
@@ -268,14 +276,25 @@ fun UserResultTab() {
) {
items(users.itemCount) { idx ->
val userItem = users[idx] ?: return@items
UserItem(userItem)
UserItem(userItem) {
scope.launch {
if (userItem.isFollowing) {
model.unfollowUser(userItem.id)
} else {
model.followUser(userItem.id)
}
}
}
}
}
}
}
@Composable
fun UserItem(accountProfile: AccountProfileEntity) {
fun UserItem(
accountProfile: AccountProfileEntity,
onFollow: (AccountProfileEntity) -> Unit = {},
) {
val context = LocalContext.current
val navController = LocalNavController.current
Row(
@@ -291,11 +310,52 @@ fun UserItem(accountProfile: AccountProfileEntity) {
context,
imageUrl = accountProfile.avatar,
modifier = Modifier
.size(64.dp)
.size(48.dp)
.clip(CircleShape),
contentDescription = null
)
Spacer(modifier = Modifier.padding(16.dp))
Text(text = accountProfile.nickName, fontSize = 18.sp, fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.padding(8.dp))
Row(
modifier = Modifier.fillMaxWidth()
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(text = accountProfile.nickName, fontSize = 16.sp, fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.padding(2.dp))
Text(
text = stringResource(
R.string.search_user_item_follower_count,
accountProfile.followerCount
), fontSize = 14.sp, color = Color(0xFF9E9E9E)
)
}
Spacer(modifier = Modifier.padding(8.dp))
if (accountProfile.id != AppState.UserId) {
if (accountProfile.isFollowing) {
ActionButton(
text = stringResource(R.string.following_upper),
backgroundColor = Color(0xFF9E9E9E),
contentPadding = PaddingValues(vertical = 4.dp, horizontal = 8.dp),
color = Color.White
) {
onFollow(accountProfile)
}
} else {
ActionButton(
text = stringResource(R.string.follow_upper),
backgroundColor = Color(0xffda3832),
contentPadding = PaddingValues(vertical = 4.dp, horizontal = 8.dp),
color = Color.White
) {
onFollow(accountProfile)
}
}
}
}
}
}

View File

@@ -9,6 +9,7 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.map
import com.aiosman.riderpro.entity.AccountPagingSource
import com.aiosman.riderpro.entity.AccountProfileEntity
import com.aiosman.riderpro.entity.MomentPagingSource
@@ -17,6 +18,7 @@ import com.aiosman.riderpro.data.MomentService
import com.aiosman.riderpro.entity.MomentServiceImpl
import com.aiosman.riderpro.data.UserServiceImpl
import com.aiosman.riderpro.entity.MomentEntity
import com.aiosman.riderpro.ui.index.tabs.moment.MomentViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
@@ -32,7 +34,11 @@ object SearchViewModel : ViewModel() {
private val _usersFlow = MutableStateFlow<PagingData<AccountProfileEntity>>(PagingData.empty())
val usersFlow = _usersFlow.asStateFlow()
var showResult by mutableStateOf(false)
var requestFocus by mutableStateOf(false)
fun search() {
if (searchText.isEmpty()) {
return
}
viewModelScope.launch {
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
@@ -62,6 +68,32 @@ object SearchViewModel : ViewModel() {
showResult = true
}
suspend fun followUser(id:Int){
userService.followUser(id.toString())
val currentPagingData = _usersFlow.value
val updatedPagingData = currentPagingData.map { userItem ->
if (userItem.id == id) {
userItem.copy(isFollowing = true, followerCount = userItem.followerCount + 1)
} else {
userItem
}
}
_usersFlow.value = updatedPagingData
}
suspend fun unfollowUser(id:Int){
userService.unFollowUser(id.toString())
val currentPagingData = _usersFlow.value
val updatedPagingData = currentPagingData.map { userItem ->
if (userItem.id == id) {
userItem.copy(isFollowing = false, followerCount = userItem.followerCount - 1)
} else {
userItem
}
}
_usersFlow.value = updatedPagingData
}
fun ResetModel(){
_momentsFlow.value = PagingData.empty()
_usersFlow.value = PagingData.empty()

View File

@@ -86,4 +86,5 @@
<string name="refresh">刷新</string>
<string name="clear">清除</string>
<string name="incorrect_captcha_please_try_again">验证码错误,请重试</string>
<string name="search_user_item_follower_count">%d 粉丝</string>
</resources>

View File

@@ -85,4 +85,5 @@
<string name="refresh">Refresh</string>
<string name="clear">Clear</string>
<string name="incorrect_captcha_please_try_again">incorrect captcha,please try again</string>
<string name="search_user_item_follower_count">%d followers</string>
</resources>