From 1fc487c73d7347a84c123be8fedd8ccd6d5a570d Mon Sep 17 00:00:00 2001 From: AllenTom Date: Fri, 6 Sep 2024 17:43:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=B8=BB=E9=A1=B5=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=B8=8B=E6=8B=89=E5=88=B7=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在个人主页界面新增下拉刷新功能,提升用户体验。 同时修复了关注按钮的样式问题,使其在 不同状态下显示正确的颜色和文字。 此外,还修复了登录后无法获取用户信息的问题,确保用户登录后能够正常使用应用。 --- .../java/com/aiosman/riderpro/AppState.kt | 5 + .../java/com/aiosman/riderpro/MainActivity.kt | 4 +- .../riderpro/ui/index/tabs/profile/Profile.kt | 28 ++-- .../aiosman/riderpro/ui/login/emailsignup.kt | 23 +++- .../com/aiosman/riderpro/ui/login/signup.kt | 6 +- .../riderpro/ui/profile/AccountProfile.kt | 120 ++++++++++-------- .../ui/profile/AccountProfileViewModel.kt | 14 +- 7 files changed, 128 insertions(+), 72 deletions(-) create mode 100644 app/src/main/java/com/aiosman/riderpro/AppState.kt diff --git a/app/src/main/java/com/aiosman/riderpro/AppState.kt b/app/src/main/java/com/aiosman/riderpro/AppState.kt new file mode 100644 index 0000000..f24df0b --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/AppState.kt @@ -0,0 +1,5 @@ +package com.aiosman.riderpro + +object AppState { + var UserId: Int? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/MainActivity.kt b/app/src/main/java/com/aiosman/riderpro/MainActivity.kt index df92ffe..bea2283 100644 --- a/app/src/main/java/com/aiosman/riderpro/MainActivity.kt +++ b/app/src/main/java/com/aiosman/riderpro/MainActivity.kt @@ -80,10 +80,12 @@ class MainActivity : ComponentActivity() { /** * 获取账号信息 */ - suspend fun getAccount(): Boolean { + private suspend fun getAccount(): Boolean { val accountService: AccountService = AccountServiceImpl() try { val resp = accountService.getMyAccount() + // 设置当前登录用户 ID + AppState.UserId = resp.id return true } catch (e: Exception) { return false diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt index d33c19b..9028660 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/profile/Profile.kt @@ -67,6 +67,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController 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 @@ -206,7 +207,10 @@ fun ProfilePage() { } }) { Row { - Text(stringResource(R.string.logout), fontWeight = FontWeight.W500) + Text( + stringResource(R.string.logout), + fontWeight = FontWeight.W500 + ) Spacer(modifier = Modifier.weight(1f)) Icon( painter = painterResource(id = R.mipmap.rider_pro_logout), @@ -225,7 +229,10 @@ fun ProfilePage() { } }) { Row { - Text(stringResource(R.string.change_password), fontWeight = FontWeight.W500) + Text( + stringResource(R.string.change_password), + fontWeight = FontWeight.W500 + ) Spacer(modifier = Modifier.weight(1f)) Icon( painter = painterResource(id = R.mipmap.rider_pro_change_password), @@ -339,7 +346,8 @@ fun UserInformation( isSelf = isSelf, isFollowing = accountProfileEntity.isFollowing, onFollowClick = onFollowClick, - onEditProfileClick = onEditProfileClick + onEditProfileClick = onEditProfileClick, + accountProfileEntity = accountProfileEntity ) } } @@ -491,6 +499,7 @@ fun UserInformationSlogan(accountProfileEntity: AccountProfileEntity) { @Composable fun CommunicationOperatorGroup( + accountProfileEntity: AccountProfileEntity, isSelf: Boolean = true, isFollowing: Boolean = false, onFollowClick: () -> Unit = {}, @@ -502,7 +511,7 @@ fun CommunicationOperatorGroup( .fillMaxWidth() .padding(top = 16.dp), horizontalArrangement = Arrangement.Center ) { - if (!isSelf) { + if (!isSelf && AppState.UserId != accountProfileEntity.id) { Box( modifier = Modifier .size(width = 142.dp, height = 40.dp) @@ -513,16 +522,18 @@ fun CommunicationOperatorGroup( ) { Image( modifier = Modifier.fillMaxSize(), - painter = painterResource(id = R.drawable.rider_pro_profile_follow), + painter = if (isFollowing) painterResource(id = R.mipmap.rider_pro_follow_grey) else painterResource( + id = R.mipmap.rider_pro_follow_red + ), contentDescription = "" ) Text( text = if (isFollowing) stringResource(R.string.following_upper) else stringResource( R.string.follow_upper ), - fontSize = 16.sp, - color = Color.White, - style = TextStyle(fontWeight = FontWeight.Bold) + fontSize = 14.sp, + color = if (isFollowing) Color.Black else Color.White, + style = TextStyle(fontWeight = FontWeight.W600, fontStyle = FontStyle.Italic), ) } } @@ -550,7 +561,6 @@ fun CommunicationOperatorGroup( ) } } - } } diff --git a/app/src/main/java/com/aiosman/riderpro/ui/login/emailsignup.kt b/app/src/main/java/com/aiosman/riderpro/ui/login/emailsignup.kt index ac603af..7f16145 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/login/emailsignup.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/login/emailsignup.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.aiosman.riderpro.AppState import com.aiosman.riderpro.AppStore import com.aiosman.riderpro.ErrorCode import com.aiosman.riderpro.LocalNavController @@ -100,20 +101,28 @@ fun EmailSignupScreen() { } if (!acceptTerms) { scope.launch(Dispatchers.Main) { - Toast.makeText(context, context.getString(R.string.error_not_accept_term), Toast.LENGTH_SHORT).show() + Toast.makeText( + context, + context.getString(R.string.error_not_accept_term), + Toast.LENGTH_SHORT + ).show() } termsError = true return false - }else{ + } else { termsError = false } if (!acceptPromotions) { scope.launch(Dispatchers.Main) { - Toast.makeText(context, context.getString(R.string.error_not_accept_recive_notice), Toast.LENGTH_SHORT).show() + Toast.makeText( + context, + context.getString(R.string.error_not_accept_recive_notice), + Toast.LENGTH_SHORT + ).show() } promotionsError = true return false - }else{ + } else { promotionsError = false } @@ -131,7 +140,8 @@ fun EmailSignupScreen() { emailError = context.getString(R.string.error_10001_user_exist) return@launch } - Toast.makeText(context, context.getErrorMessageCode(e.code), Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getErrorMessageCode(e.code), Toast.LENGTH_SHORT) + .show() } return } catch (e: Exception) { @@ -154,7 +164,8 @@ fun EmailSignupScreen() { } // 获取token 信息 try { - accountService.getMyAccount() + val resp = accountService.getMyAccount() + AppState.UserId = resp.id Messaging.InitFCM(scope) } catch (e: ServiceException) { scope.launch(Dispatchers.Main) { diff --git a/app/src/main/java/com/aiosman/riderpro/ui/login/signup.kt b/app/src/main/java/com/aiosman/riderpro/ui/login/signup.kt index 0051071..5e88129 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/login/signup.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/login/signup.kt @@ -28,6 +28,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.aiosman.riderpro.AppState import com.aiosman.riderpro.AppStore import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.Messaging @@ -53,7 +54,7 @@ fun SignupScreen() { fun googleLogin() { coroutineScope.launch { try { - + GoogleLogin(context) { coroutineScope.launch { try { @@ -82,7 +83,8 @@ fun SignupScreen() { } // 获取token 信息 try { - accountService.getMyAccount() + val resp = accountService.getMyAccount() + AppState.UserId = resp.id Messaging.InitFCM(coroutineScope) } catch (e: ServiceException) { coroutineScope.launch(Dispatchers.Main) { diff --git a/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfile.kt b/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfile.kt index e9bf707..4c68510 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfile.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfile.kt @@ -1,18 +1,25 @@ package com.aiosman.riderpro.ui.profile import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -24,73 +31,84 @@ import com.aiosman.riderpro.ui.index.tabs.profile.MomentPostUnit import com.aiosman.riderpro.ui.index.tabs.profile.UserInformation import kotlinx.coroutines.launch +@OptIn(ExperimentalMaterialApi::class) @Composable fun AccountProfile(id: String) { val model = AccountProfileViewModel val scope = rememberCoroutineScope() val items = model.momentsFlow.collectAsLazyPagingItems() + val state = rememberPullRefreshState(model.refreshing, onRefresh = { + model.loadProfile(id,pullRefresh = true) + }) LaunchedEffect(Unit) { model.loadProfile(id) } - - LazyColumn( + Box( modifier = Modifier - .fillMaxSize() - .padding(bottom = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Top, + .fillMaxSize().background(Color.White).pullRefresh(state) ) { - item { - Box( - modifier = Modifier - .fillMaxWidth() + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top, + ) { + item { + Box( + modifier = Modifier + .fillMaxWidth() - ) { - val banner = model.profile?.banner - if (banner != null) { - CustomAsyncImage( - LocalContext.current, - banner, - modifier = Modifier - .fillMaxWidth() - .height(400.dp), - contentDescription = "", - contentScale = ContentScale.Crop - ) - } else { - Image( - painter = painterResource(id = R.drawable.rider_pro_moment_demo_2), - modifier = Modifier - .fillMaxWidth() - .height(400.dp), - contentDescription = "", - contentScale = ContentScale.Crop + ) { + val banner = model.profile?.banner + if (banner != null) { + CustomAsyncImage( + LocalContext.current, + banner, + modifier = Modifier + .fillMaxWidth() + .height(400.dp), + contentDescription = "", + contentScale = ContentScale.Crop + ) + } else { + Image( + painter = painterResource(id = R.drawable.rider_pro_moment_demo_2), + modifier = Modifier + .fillMaxWidth() + .height(400.dp), + contentDescription = "", + contentScale = ContentScale.Crop + ) + } + } + Spacer(modifier = Modifier.height(32.dp)) + model.profile?.let { + UserInformation( + isSelf = false, + accountProfileEntity = it, + onFollowClick = { + scope.launch { + if (it.isFollowing) { + model.unFollowUser(id) + } else { + model.followUser(id) + } + } + }, ) } - } - model.profile?.let { - UserInformation( - isSelf = false, - accountProfileEntity = it, - onFollowClick = { - scope.launch { - if (it.isFollowing) { - model.unFollowUser(id) - } else { - model.followUser(id) - } - } - }, - ) - } // RidingStyle() - } + } - items(items.itemCount) { idx -> - val momentItem = items[idx] ?: return@items - MomentPostUnit(momentItem) - } + items(items.itemCount) { idx -> + val momentItem = items[idx] ?: return@items + MomentPostUnit(momentItem) + } + } + PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter)) } + } \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfileViewModel.kt b/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfileViewModel.kt index 9961e0b..fe7ae9b 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfileViewModel.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/profile/AccountProfileViewModel.kt @@ -31,12 +31,17 @@ object AccountProfileViewModel : ViewModel() { var profile by mutableStateOf(null) private var _momentsFlow = MutableStateFlow>(PagingData.empty()) var momentsFlow = _momentsFlow.asStateFlow() - fun loadProfile(id: String) { + var refreshing by mutableStateOf(false) + fun loadProfile(id: String, pullRefresh: Boolean = false) { viewModelScope.launch { - if (profileId == profile?.id){ + if (pullRefresh) { + refreshing = true + } + if (profileId == profile?.id) { return@launch } profile = userService.getUserProfile(id) + refreshing = false Pager( config = PagingConfig(pageSize = 5, enablePlaceholders = false), pagingSourceFactory = { @@ -50,6 +55,7 @@ object AccountProfileViewModel : ViewModel() { } } } + fun followUser(userId: String) { viewModelScope.launch { userService.followUser(userId) @@ -60,9 +66,11 @@ object AccountProfileViewModel : ViewModel() { fun unFollowUser(userId: String) { viewModelScope.launch { userService.unFollowUser(userId) - profile = profile?.copy(followerCount = profile!!.followerCount - 1, isFollowing = false) + profile = + profile?.copy(followerCount = profile!!.followerCount - 1, isFollowing = false) } } + val followerCount get() = profile?.followerCount ?: 0 val followingCount get() = profile?.followingCount ?: 0 val bio get() = profile?.bio ?: ""