更新登录UI
This commit is contained in:
@@ -145,10 +145,9 @@ fun ResetPasswordScreen() {
|
|||||||
TextInputField(
|
TextInputField(
|
||||||
text = username,
|
text = username,
|
||||||
onValueChange = { username = it },
|
onValueChange = { username = it },
|
||||||
label = stringResource(R.string.login_email_label),
|
|
||||||
hint = stringResource(R.string.text_hint_email),
|
hint = stringResource(R.string.text_hint_email),
|
||||||
enabled = !isLoading,
|
enabled = !isLoading,
|
||||||
error = usernameError
|
error = usernameError,
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(72.dp))
|
Spacer(modifier = Modifier.height(72.dp))
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@@ -159,7 +158,8 @@ fun ResetPasswordScreen() {
|
|||||||
.width(345.dp)
|
.width(345.dp)
|
||||||
.height(48.dp),
|
.height(48.dp),
|
||||||
text = stringResource(R.string.recover),
|
text = stringResource(R.string.recover),
|
||||||
backgroundImage = R.mipmap.rider_pro_signup_red_bg
|
backgroundColor = Color(0xffda3832),
|
||||||
|
|
||||||
) {
|
) {
|
||||||
resetPassword()
|
resetPassword()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
package com.aiosman.riderpro.ui.composables
|
package com.aiosman.riderpro.ui.composables
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
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.layout.ContentScale
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
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.compose.ui.unit.sp
|
||||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
|
|
||||||
@@ -21,28 +23,38 @@ import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
|||||||
fun ActionButton(
|
fun ActionButton(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
text: String,
|
text: String,
|
||||||
color: Color = Color.White,
|
color: Color = Color.Black,
|
||||||
@DrawableRes backgroundImage: Int,
|
@DrawableRes backgroundImage: Int? = null,
|
||||||
|
backgroundColor: Color = Color(0xfff0f0f0),
|
||||||
leading: @Composable (() -> Unit)? = null,
|
leading: @Composable (() -> Unit)? = null,
|
||||||
|
expandText: Boolean = false,
|
||||||
|
contentPadding: PaddingValues = PaddingValues(vertical = 16.dp),
|
||||||
click: () -> Unit = {}
|
click: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.noRippleClickable {
|
modifier = modifier
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(backgroundColor)
|
||||||
|
.padding(contentPadding)
|
||||||
|
.noRippleClickable {
|
||||||
click()
|
click()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Image(
|
|
||||||
painter = painterResource(id = backgroundImage),
|
|
||||||
contentDescription = "Rider Pro",
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
contentScale = ContentScale.FillBounds
|
|
||||||
)
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
leading?.invoke()
|
leading?.invoke()
|
||||||
Text(text, fontSize = 14.sp, color = color, fontWeight = FontWeight.W600, fontStyle = FontStyle.Italic)
|
Text(
|
||||||
|
text,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = color,
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
modifier = Modifier.let {
|
||||||
|
if (expandText) it.weight(1f) else it
|
||||||
|
},
|
||||||
|
textAlign = if (expandText) TextAlign.Center else TextAlign.Start
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import androidx.compose.foundation.border
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
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.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
@@ -34,8 +36,9 @@ fun Checkbox(
|
|||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
onCheckedChange(!checked)
|
onCheckedChange(!checked)
|
||||||
}
|
}
|
||||||
|
.clip(CircleShape)
|
||||||
.background(color = backgroundColor)
|
.background(color = backgroundColor)
|
||||||
.border(width = borderWidth, color = borderColor)
|
.border(width = borderWidth, color = borderColor, shape = CircleShape)
|
||||||
.padding(2.dp)
|
.padding(2.dp)
|
||||||
) {
|
) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
|||||||
@@ -6,13 +6,16 @@ import androidx.compose.animation.fadeIn
|
|||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -25,6 +28,7 @@ import androidx.compose.runtime.remember
|
|||||||
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.focus.onFocusChanged
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
@@ -58,7 +62,16 @@ fun TextInputField(
|
|||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.CenterStart
|
contentAlignment = Alignment.CenterStart,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(Color(0xFFF7f7f7))
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = if (error == null) Color.Transparent else Color(0xFFE53935),
|
||||||
|
shape = RoundedCornerShape(24.dp)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 16.dp)
|
||||||
) {
|
) {
|
||||||
Row {
|
Row {
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
@@ -97,18 +110,10 @@ fun TextInputField(
|
|||||||
|
|
||||||
if (text.isEmpty()) {
|
if (text.isEmpty()) {
|
||||||
hint?.let {
|
hint?.let {
|
||||||
Text(it, color = Color(0xFFCCCCCC), fontWeight = FontWeight.W600)
|
Text(it, color = Color(0xffdadada), fontWeight = FontWeight.W600)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(1.dp)
|
|
||||||
.background(if (isFocused) Color(0xff333333) else Color(0xFFF5F5F5))
|
|
||||||
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
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.alpha
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
@@ -137,7 +138,7 @@ fun Profile(
|
|||||||
var headerBannerMaxHeight: Int = userHeight + bannerHeight
|
var headerBannerMaxHeight: Int = userHeight + bannerHeight
|
||||||
val headerBannerMinHeight = 100
|
val headerBannerMinHeight = 100
|
||||||
val speedFactor = 0.5f
|
val speedFactor = 0.5f
|
||||||
var currentHeaderHeight by rememberSaveable{ mutableStateOf<Int>(headerBannerMaxHeight) }
|
var currentHeaderHeight by rememberSaveable { mutableStateOf<Int>(headerBannerMaxHeight) }
|
||||||
var scrollState = rememberLazyListState()
|
var scrollState = rememberLazyListState()
|
||||||
var gridScrollState = rememberLazyStaggeredGridState()
|
var gridScrollState = rememberLazyStaggeredGridState()
|
||||||
var pagerState = rememberPagerState(pageCount = { 2 })
|
var pagerState = rememberPagerState(pageCount = { 2 })
|
||||||
@@ -332,13 +333,15 @@ fun Profile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
// user info
|
// user info
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(if (currentHeaderHeight.dp > bannerHeight.dp) userHeight.dp else currentHeaderHeight.dp)
|
.height(if (currentHeaderHeight.dp > bannerHeight.dp) userHeight.dp else currentHeaderHeight.dp)
|
||||||
) {
|
) {
|
||||||
if (currentHeaderHeight.dp > headerBannerMinHeight.dp) {
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
// 个人信息
|
// 个人信息
|
||||||
Box(
|
Box(
|
||||||
@@ -371,14 +374,35 @@ fun Profile(
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collapsed bar
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
val thresholdHeight = 200 // 设置阈值高度
|
||||||
|
val startChangeHeight = headerBannerMinHeight + thresholdHeight
|
||||||
|
val alpha = if (currentHeaderHeight < startChangeHeight) {
|
||||||
|
((currentHeaderHeight - headerBannerMinHeight).toFloat() / thresholdHeight.toFloat()).coerceIn(
|
||||||
|
0f,
|
||||||
|
1f
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
StatusBarSpacer()
|
1f // 高度大于阈值时,alpha 为 0
|
||||||
Row(
|
}
|
||||||
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(headerBannerMinHeight.dp)
|
// 保持在最低高度和当前高度之间
|
||||||
// .background(Color(0xfff8f8f8))
|
.alpha(1 - alpha)
|
||||||
.padding(horizontal = 16.dp),
|
.background(Color(0xfff8f8f8))
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
|
||||||
|
|
||||||
|
) {
|
||||||
|
StatusBarSpacer()
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.height(headerBannerMinHeight.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
CustomAsyncImage(
|
CustomAsyncImage(
|
||||||
@@ -398,11 +422,11 @@ fun Profile(
|
|||||||
color = Color.Black
|
color = Color.Black
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Spacer(modifier = Modifier.height(currentHeaderHeight.dp - headerBannerMinHeight.dp))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -512,7 +536,9 @@ fun Profile(
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(300.dp)
|
.aspectRatio(
|
||||||
|
if (idx % 3 == 0) 1.5f else 1f
|
||||||
|
)
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
navController.navigateToPost(
|
navController.navigateToPost(
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.aiosman.riderpro.ui.login
|
package com.aiosman.riderpro.ui.login
|
||||||
|
|
||||||
import android.icu.util.Calendar
|
|
||||||
import android.icu.util.TimeZone
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@@ -28,7 +26,6 @@ import com.aiosman.riderpro.AppState
|
|||||||
import com.aiosman.riderpro.AppStore
|
import com.aiosman.riderpro.AppStore
|
||||||
import com.aiosman.riderpro.ErrorCode
|
import com.aiosman.riderpro.ErrorCode
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.Messaging
|
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
import com.aiosman.riderpro.data.AccountService
|
import com.aiosman.riderpro.data.AccountService
|
||||||
import com.aiosman.riderpro.data.ServiceException
|
import com.aiosman.riderpro.data.ServiceException
|
||||||
@@ -41,7 +38,6 @@ import com.aiosman.riderpro.ui.composables.CheckboxWithLabel
|
|||||||
import com.aiosman.riderpro.ui.composables.PolicyCheckbox
|
import com.aiosman.riderpro.ui.composables.PolicyCheckbox
|
||||||
import com.aiosman.riderpro.ui.composables.StatusBarSpacer
|
import com.aiosman.riderpro.ui.composables.StatusBarSpacer
|
||||||
import com.aiosman.riderpro.ui.composables.TextInputField
|
import com.aiosman.riderpro.ui.composables.TextInputField
|
||||||
import com.aiosman.riderpro.utils.Utils
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -182,7 +178,7 @@ fun EmailSignupScreen() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp)
|
.padding(top = 16.dp, start = 16.dp, end = 16.dp)
|
||||||
) {
|
) {
|
||||||
NoticeScreenHeader(stringResource(R.string.sign_in_upper), moreIcon = false)
|
NoticeScreenHeader(stringResource(R.string.sign_up_upper), moreIcon = false)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.padding(32.dp))
|
Spacer(modifier = Modifier.padding(32.dp))
|
||||||
Column(
|
Column(
|
||||||
@@ -198,7 +194,6 @@ fun EmailSignupScreen() {
|
|||||||
onValueChange = {
|
onValueChange = {
|
||||||
email = it
|
email = it
|
||||||
},
|
},
|
||||||
label = stringResource(R.string.login_email_label),
|
|
||||||
hint = stringResource(R.string.text_hint_email),
|
hint = stringResource(R.string.text_hint_email),
|
||||||
error = emailError
|
error = emailError
|
||||||
)
|
)
|
||||||
@@ -211,7 +206,6 @@ fun EmailSignupScreen() {
|
|||||||
password = it
|
password = it
|
||||||
},
|
},
|
||||||
password = true,
|
password = true,
|
||||||
label = stringResource(R.string.login_password_label),
|
|
||||||
hint = stringResource(R.string.text_hint_password),
|
hint = stringResource(R.string.text_hint_password),
|
||||||
error = passwordError
|
error = passwordError
|
||||||
)
|
)
|
||||||
@@ -224,7 +218,6 @@ fun EmailSignupScreen() {
|
|||||||
confirmPassword = it
|
confirmPassword = it
|
||||||
},
|
},
|
||||||
password = true,
|
password = true,
|
||||||
label = stringResource(R.string.login_confirm_password_label),
|
|
||||||
hint = stringResource(R.string.text_hint_confirm_password),
|
hint = stringResource(R.string.text_hint_confirm_password),
|
||||||
error = confirmPasswordError
|
error = confirmPasswordError
|
||||||
)
|
)
|
||||||
@@ -279,7 +272,8 @@ fun EmailSignupScreen() {
|
|||||||
.width(345.dp)
|
.width(345.dp)
|
||||||
.height(48.dp),
|
.height(48.dp),
|
||||||
text = stringResource(R.string.lets_ride_upper),
|
text = stringResource(R.string.lets_ride_upper),
|
||||||
backgroundImage = R.mipmap.rider_pro_signup_red_bg
|
backgroundColor = Color(0xffda3832),
|
||||||
|
color = Color.White
|
||||||
) {
|
) {
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
registerUser()
|
registerUser()
|
||||||
|
|||||||
@@ -1,104 +1,241 @@
|
|||||||
package com.aiosman.riderpro.ui.login
|
package com.aiosman.riderpro.ui.login
|
||||||
|
|
||||||
|
import android.content.ContentValues.TAG
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
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
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
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.layout.width
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
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.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
|
||||||
|
import com.aiosman.riderpro.AppState
|
||||||
|
import com.aiosman.riderpro.AppStore
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
|
import com.aiosman.riderpro.data.AccountServiceImpl
|
||||||
|
import com.aiosman.riderpro.data.ServiceException
|
||||||
import com.aiosman.riderpro.ui.NavigationRoute
|
import com.aiosman.riderpro.ui.NavigationRoute
|
||||||
import com.aiosman.riderpro.ui.composables.ActionButton
|
import com.aiosman.riderpro.ui.composables.ActionButton
|
||||||
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
|
import com.aiosman.riderpro.utils.GoogleLogin
|
||||||
|
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||||
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LoginPage() {
|
fun LoginPage() {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val accountService = AccountServiceImpl()
|
||||||
|
val statusBarController = rememberSystemUiController()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
// navController.navigate(NavigationRoute.Index.route)
|
statusBarController.setStatusBarColor(Color.Transparent, darkIcons = true)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun googleLogin() {
|
||||||
|
coroutineScope.launch {
|
||||||
|
try {
|
||||||
|
GoogleLogin(context) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
try {
|
||||||
|
accountService.regiterUserWithGoogleAccount(it)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to register with google", e)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
// 获取用户信息
|
||||||
|
// 获取 token
|
||||||
|
val authResp = accountService.loginUserWithGoogle(it)
|
||||||
|
if (authResp.token != null) {
|
||||||
|
coroutineScope.launch(Dispatchers.Main) {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
"Successfully registered",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppStore.apply {
|
||||||
|
token = authResp.token
|
||||||
|
this.rememberMe = true
|
||||||
|
saveData()
|
||||||
|
}
|
||||||
|
// 获取token 信息
|
||||||
|
try {
|
||||||
|
AppState.initWithAccount(coroutineScope, context)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to init with account", e)
|
||||||
|
} catch (e: ServiceException) {
|
||||||
|
coroutineScope.launch(Dispatchers.Main) {
|
||||||
|
Toast.makeText(context, "Failed to get account", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
coroutineScope.launch(Dispatchers.Main) {
|
||||||
|
navController.navigate(NavigationRoute.Index.route) {
|
||||||
|
popUpTo(NavigationRoute.Login.route) { inclusive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Scaffold {
|
|
||||||
it
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize().background(Color.White)
|
||||||
) {
|
) {
|
||||||
|
// bg image
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth().height(900.dp).offset(
|
||||||
|
y = (-72).dp
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.rider_pro_login_bg),
|
||||||
|
contentDescription = "Login Background",
|
||||||
|
modifier = Modifier.fillMaxWidth().fillMaxHeight(),
|
||||||
|
contentScale = androidx.compose.ui.layout.ContentScale.Crop,
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.fillMaxHeight()
|
||||||
|
.background(Color.White.copy(alpha = 0.8f)),
|
||||||
|
contentAlignment = Alignment.BottomCenter
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(300.dp)
|
||||||
|
.background(
|
||||||
|
Brush.verticalGradient(
|
||||||
|
colors = listOf(
|
||||||
|
Color.Transparent,
|
||||||
|
Color.White
|
||||||
|
),
|
||||||
|
startY = 0f,
|
||||||
|
endY = 300f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(horizontal = 24.dp),
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
// to bottom
|
// to bottom
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.TopCenter,
|
contentAlignment = Alignment.TopCenter,
|
||||||
modifier = Modifier.padding(top = 211.dp)
|
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.mipmap.rider_pro_logo),
|
painter = painterResource(id = R.mipmap.rider_pro_color_logo),
|
||||||
contentDescription = "Rider Pro",
|
contentDescription = "Rider Pro",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(108.dp)
|
.size(48.dp)
|
||||||
.height(45.dp)
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(32.dp))
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
Text(
|
Text(
|
||||||
"Connecting Riders".uppercase(),
|
"Connecting Riders".uppercase(),
|
||||||
fontSize = 28.sp,
|
fontSize = 28.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.W600
|
||||||
)
|
)
|
||||||
Text("Worldwide".uppercase(), fontSize = 28.sp, fontWeight = FontWeight.Bold)
|
Text("Worldwide".uppercase(), fontSize = 28.sp, fontWeight = FontWeight.W600)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Box(
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.BottomCenter)
|
|
||||||
.padding(bottom = 82.dp + 162.dp)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
ActionButton(
|
ActionButton(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth(),
|
||||||
.width(162.dp)
|
text = stringResource(R.string.sign_up_upper),
|
||||||
.height(48.dp),
|
color = Color.White,
|
||||||
text = stringResource(R.string.login_upper),
|
backgroundColor = Color(0xffda3832)
|
||||||
backgroundImage = R.mipmap.rider_pro_grey_bg_big
|
|
||||||
) {
|
) {
|
||||||
|
navController.navigate(
|
||||||
|
NavigationRoute.EmailSignUp.route,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
ActionButton(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
text = stringResource(R.string.sign_in_with_google),
|
||||||
|
color = Color.Black,
|
||||||
|
leading = {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_google),
|
||||||
|
contentDescription = "Google",
|
||||||
|
modifier = Modifier.size(36.dp)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
expandText = true,
|
||||||
|
contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
googleLogin()
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.login_upper),
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
color = Color(0xff333333),
|
||||||
|
modifier = Modifier.noRippleClickable {
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
NavigationRoute.UserAuth.route,
|
NavigationRoute.UserAuth.route,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ActionButton(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(162.dp)
|
|
||||||
.height(48.dp),
|
|
||||||
text = stringResource(R.string.sign_in_upper),
|
|
||||||
backgroundImage = R.mipmap.rider_pro_red_bg_big
|
|
||||||
){
|
|
||||||
navController.navigate(
|
|
||||||
NavigationRoute.SignUp.route,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
Spacer(modifier = Modifier.height(120.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@@ -164,7 +165,6 @@ fun UserAuthScreen() {
|
|||||||
onValueChange = {
|
onValueChange = {
|
||||||
email = it
|
email = it
|
||||||
},
|
},
|
||||||
label = stringResource(R.string.login_email_label),
|
|
||||||
hint = stringResource(R.string.text_hint_email),
|
hint = stringResource(R.string.text_hint_email),
|
||||||
error = emailError
|
error = emailError
|
||||||
)
|
)
|
||||||
@@ -177,7 +177,6 @@ fun UserAuthScreen() {
|
|||||||
password = it
|
password = it
|
||||||
},
|
},
|
||||||
password = true,
|
password = true,
|
||||||
label = stringResource(R.string.login_password_label),
|
|
||||||
hint = stringResource(R.string.text_hint_password),
|
hint = stringResource(R.string.text_hint_password),
|
||||||
error = passwordError
|
error = passwordError
|
||||||
)
|
)
|
||||||
@@ -229,34 +228,31 @@ fun UserAuthScreen() {
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(64.dp))
|
Spacer(modifier = Modifier.height(64.dp))
|
||||||
ActionButton(
|
ActionButton(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth(),
|
||||||
.width(345.dp)
|
|
||||||
.height(48.dp),
|
|
||||||
text = stringResource(R.string.lets_ride_upper),
|
text = stringResource(R.string.lets_ride_upper),
|
||||||
backgroundImage = R.mipmap.rider_pro_signup_red_bg
|
backgroundColor = Color(0xffda3832),
|
||||||
|
color = Color.White
|
||||||
) {
|
) {
|
||||||
onLogin()
|
onLogin()
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(48.dp))
|
Spacer(modifier = Modifier.height(48.dp))
|
||||||
Text(stringResource(R.string.or_login_with), color = Color(0xFF999999))
|
Text(stringResource(R.string.or_login_with), color = Color(0xFF999999))
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Row {
|
ActionButton(
|
||||||
Box(
|
modifier = Modifier.fillMaxWidth(),
|
||||||
modifier = Modifier
|
text = stringResource(R.string.sign_in_with_google),
|
||||||
.size(96.dp)
|
color = Color.Black,
|
||||||
.padding(16.dp)
|
leading = {
|
||||||
.border(2.dp, Color(0xFFEBEBEB))
|
|
||||||
.noRippleClickable {
|
|
||||||
// login with facebook
|
|
||||||
googleLogin()
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_google),
|
painter = painterResource(id = R.drawable.rider_pro_google),
|
||||||
contentDescription = "Google",
|
contentDescription = "Google",
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.size(36.dp)
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
expandText = true,
|
||||||
|
contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp)
|
||||||
|
){
|
||||||
|
googleLogin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<string name="text_error_password_required">密码是必填项</string>
|
<string name="text_error_password_required">密码是必填项</string>
|
||||||
<string name="text_hint_email">输入邮箱</string>
|
<string name="text_hint_email">输入邮箱</string>
|
||||||
<string name="text_hint_password">输入密码</string>
|
<string name="text_hint_password">输入密码</string>
|
||||||
<string name="sign_in_upper">注册</string>
|
<string name="sign_up_upper">注册</string>
|
||||||
<string name="sign_in_with_email">使用邮箱注册</string>
|
<string name="sign_in_with_email">使用邮箱注册</string>
|
||||||
<string name="sign_in_with_google">使用 Google 账号登录</string>
|
<string name="sign_in_with_google">使用 Google 账号登录</string>
|
||||||
<string name="back_upper">返回</string>
|
<string name="back_upper">返回</string>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<string name="text_error_password_required">Password is required</string>
|
<string name="text_error_password_required">Password is required</string>
|
||||||
<string name="text_hint_email">Enter your email</string>
|
<string name="text_hint_email">Enter your email</string>
|
||||||
<string name="text_hint_password">Enter your password</string>
|
<string name="text_hint_password">Enter your password</string>
|
||||||
<string name="sign_in_upper">SIGN IN</string>
|
<string name="sign_up_upper">SIGN UP</string>
|
||||||
<string name="sign_in_with_email">CONTINUE WITH EMAIL</string>
|
<string name="sign_in_with_email">CONTINUE WITH EMAIL</string>
|
||||||
<string name="sign_in_with_google">CONTINUE WITH GOOGLE</string>
|
<string name="sign_in_with_google">CONTINUE WITH GOOGLE</string>
|
||||||
<string name="back_upper">BACK</string>
|
<string name="back_upper">BACK</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user