新增登录

This commit is contained in:
2024-07-30 16:57:25 +08:00
parent f28236b365
commit 2c79195f44
8 changed files with 237 additions and 63 deletions

View File

@@ -64,14 +64,14 @@ sealed class NavigationRoute(
@Composable
fun NavigationController(navController: NavHostController) {
fun NavigationController(navController: NavHostController,startDestination: String = NavigationRoute.Login.route) {
val navigationBarHeight = with(LocalDensity.current) {
WindowInsets.navigationBars.getBottom(this).toDp()
}
NavHost(
navController = navController,
startDestination = NavigationRoute.Index.route,
startDestination = startDestination,
) {
composable(route = NavigationRoute.Index.route) {
CompositionLocalProvider(
@@ -170,7 +170,7 @@ fun NavigationController(navController: NavHostController) {
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun Navigation() {
fun Navigation(startDestination: String = NavigationRoute.Login.route) {
val navController = rememberNavController()
SharedTransitionLayout {
CompositionLocalProvider(
@@ -178,7 +178,7 @@ fun Navigation() {
LocalSharedTransitionScope provides this@SharedTransitionLayout,
) {
Box {
NavigationController(navController = navController)
NavigationController(navController = navController,startDestination = startDestination)
}
}
}

View File

@@ -66,14 +66,6 @@ fun IndexScreen() {
selected = isSelected,
onClick = {
model.tabIndex = idx
// if (it.route == NavigationItem.Add.route || it.route == NavigationItem.Message.route) {
// systemUiController.setStatusBarColor(Color.Black, darkIcons = false)
// } else {
// systemUiController.setStatusBarColor(
// Color.Transparent,
// darkIcons = true
// )
// }
},
colors = NavigationBarItemColors(
selectedTextColor = Color.Red,

View File

@@ -3,20 +3,25 @@ package com.aiosman.riderpro.ui.index.tabs.profile
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.navigation.NavController
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.aiosman.riderpro.AppStore
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.data.AccountProfile
import com.aiosman.riderpro.data.AccountService
import com.aiosman.riderpro.data.TestAccountServiceImpl
import com.aiosman.riderpro.data.MomentPagingSource
import com.aiosman.riderpro.data.MomentRemoteDataSource
import com.aiosman.riderpro.data.TestMomentServiceImpl
import com.aiosman.riderpro.data.TestUserServiceImpl
import com.aiosman.riderpro.model.MomentItem
import kotlinx.coroutines.flow.Flow
object MyProfileViewModel {
val service: AccountService = TestAccountServiceImpl()
val userService = TestUserServiceImpl()
var profile by mutableStateOf<AccountProfile?>(null)
var momentsFlow by mutableStateOf<Flow<PagingData<MomentItem>>?>(null)
suspend fun loadProfile() {
@@ -32,6 +37,15 @@ object MyProfileViewModel {
}
).flow
}
suspend fun logout() {
service.getMyAccountProfile()
AppStore.apply {
token = null
rememberMe = false
saveData()
}
}
val followerCount get() = profile?.followerCount ?: 0
val followingCount get() = profile?.followingCount ?: 0
val bio get() = profile?.bio ?: ""

View File

@@ -20,9 +20,17 @@ import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
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
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -35,44 +43,90 @@ 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.navigation.NavController
import androidx.paging.compose.collectAsLazyPagingItems
import coil.compose.AsyncImage
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R
import com.aiosman.riderpro.data.AccountProfile
import com.aiosman.riderpro.model.MomentItem
import com.aiosman.riderpro.ui.NavigationRoute
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import kotlinx.coroutines.launch
@Composable
fun ProfilePage() {
val model = MyProfileViewModel
var expanded by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
model.loadProfile()
}
val moments = model.momentsFlow?.collectAsLazyPagingItems()
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
) {
item {
CarGroup()
model.profile?.let {
UserInformation(accountProfile = it)
val navController: NavController = LocalNavController.current
val scope = rememberCoroutineScope()
Box {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
) {
item {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp, start = 16.dp, end = 16.dp)
) {
Box(
modifier = Modifier.align(Alignment.TopEnd)
) {
Icon(
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
contentDescription = "",
modifier = Modifier.noRippleClickable {
expanded = true
}
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(onClick = {
scope.launch {
model.logout()
navController.navigate(NavigationRoute.Login.route) {
popUpTo(NavigationRoute.Index.route) {
inclusive = true
}
}
}
}, text = {
Text("Logout")
})
}
}
}
CarGroup()
model.profile?.let {
UserInformation(accountProfile = it)
}
RidingStyle()
}
moments?.let {
items(it.itemCount) { idx ->
val momentItem = it[idx] ?: return@items
MomentPostUnit(momentItem)
}
}
RidingStyle()
}
moments?.let {
items(it.itemCount) { idx ->
val momentItem = it[idx] ?: return@items
MomentPostUnit(momentItem)
}
}
}
}
@Composable
@@ -123,7 +177,7 @@ fun CarTopPicture() {
}
@Composable
fun UserInformation(isSelf: Boolean = true,accountProfile: AccountProfile) {
fun UserInformation(isSelf: Boolean = true, accountProfile: AccountProfile) {
Column(
modifier = Modifier
.fillMaxWidth()
@@ -132,9 +186,9 @@ fun UserInformation(isSelf: Boolean = true,accountProfile: AccountProfile) {
) {
Row(modifier = Modifier.fillMaxWidth()) {
val userInfoModifier = Modifier.weight(1f)
UserInformationFollowers(userInfoModifier,accountProfile)
UserInformationBasic(userInfoModifier,accountProfile)
UserInformationFollowing(userInfoModifier,accountProfile)
UserInformationFollowers(userInfoModifier, accountProfile)
UserInformationBasic(userInfoModifier, accountProfile)
UserInformationFollowing(userInfoModifier, accountProfile)
}
UserInformationSlogan()
CommunicationOperatorGroup(isSelf = isSelf)
@@ -142,7 +196,7 @@ fun UserInformation(isSelf: Boolean = true,accountProfile: AccountProfile) {
}
@Composable
fun UserInformationFollowers(modifier: Modifier,accountProfile: AccountProfile) {
fun UserInformationFollowers(modifier: Modifier, accountProfile: AccountProfile) {
Column(modifier = modifier.padding(top = 31.dp)) {
Text(
modifier = Modifier.padding(bottom = 5.dp),
@@ -168,7 +222,7 @@ fun UserInformationFollowers(modifier: Modifier,accountProfile: AccountProfile)
}
@Composable
fun UserInformationBasic(modifier: Modifier,accountProfile: AccountProfile) {
fun UserInformationBasic(modifier: Modifier, accountProfile: AccountProfile) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
@@ -193,7 +247,9 @@ fun UserInformationBasic(modifier: Modifier,accountProfile: AccountProfile) {
}
Text(
modifier = Modifier.widthIn(max =220.dp).padding(top = 8.dp),
modifier = Modifier
.widthIn(max = 220.dp)
.padding(top = 8.dp),
text = accountProfile.nickName,
fontSize = 32.sp,
color = Color.Black,
@@ -216,7 +272,7 @@ fun UserInformationBasic(modifier: Modifier,accountProfile: AccountProfile) {
}
@Composable
fun UserInformationFollowing(modifier: Modifier,accountProfile: AccountProfile) {
fun UserInformationFollowing(modifier: Modifier, accountProfile: AccountProfile) {
Column(
modifier = modifier.padding(top = 6.dp),
horizontalAlignment = Alignment.End
@@ -264,22 +320,25 @@ fun CommunicationOperatorGroup(isSelf: Boolean = true) {
.fillMaxWidth()
.padding(top = 16.dp), horizontalArrangement = Arrangement.Center
) {
Box(
modifier = Modifier.size(width = 142.dp, height = 40.dp),
contentAlignment = Alignment.Center
) {
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(id = R.drawable.rider_pro_profile_follow),
contentDescription = ""
)
Text(
text = "FOLLOW",
fontSize = 16.sp,
color = Color.White,
style = TextStyle(fontWeight = FontWeight.Bold)
)
if (!isSelf) {
Box(
modifier = Modifier.size(width = 142.dp, height = 40.dp),
contentAlignment = Alignment.Center
) {
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(id = R.drawable.rider_pro_profile_follow),
contentDescription = ""
)
Text(
text = "FOLLOW",
fontSize = 16.sp,
color = Color.White,
style = TextStyle(fontWeight = FontWeight.Bold)
)
}
}
if (isSelf) {
Box(
modifier = Modifier
@@ -469,7 +528,7 @@ fun MomentCardTopContent(content: String) {
}
@Composable
fun MomentCardPicture(imageUrl:String) {
fun MomentCardPicture(imageUrl: String) {
AsyncImage(
imageUrl,
modifier = Modifier

View File

@@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -33,10 +34,17 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.riderpro.AppStore
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R
import com.aiosman.riderpro.data.TestUserServiceImpl
import com.aiosman.riderpro.data.UserService
import com.aiosman.riderpro.ui.NavigationRoute
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -44,6 +52,25 @@ fun UserAuthScreen() {
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var rememberMe by remember { mutableStateOf(false) }
var userService: UserService = TestUserServiceImpl()
val scope = rememberCoroutineScope()
val navController = LocalNavController.current
fun onLogin() {
scope.launch {
val authResp = userService.loginUserWithPassword(email, password)
if (authResp.token != null) {
AppStore.apply {
token = authResp.token
this.rememberMe = rememberMe
saveData()
}
navController.navigate(NavigationRoute.Index.route) {
popUpTo(NavigationRoute.Login.route) { inclusive = true }
}
}
}
}
StatusBarMaskLayout {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
@@ -106,7 +133,9 @@ fun UserAuthScreen() {
.height(48.dp),
text = "LET'S RIDE".uppercase(),
backgroundImage = R.mipmap.rider_pro_signup_red_bg
)
) {
onLogin()
}
Spacer(modifier = Modifier.height(121.dp))
Text("or login with", color = Color(0xFF999999))
@@ -153,9 +182,11 @@ fun TextInputField(
Image(
painter = painterResource(id = R.drawable.rider_pro_eye),
contentDescription = "Password",
modifier = Modifier.size(24.dp).noRippleClickable {
showPassword = !showPassword
},
modifier = Modifier
.size(24.dp)
.noRippleClickable {
showPassword = !showPassword
},
colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(Color.Black)
)
}