更新重置密码

This commit is contained in:
2024-09-12 23:13:11 +08:00
parent 1186e3a8a5
commit 5c3c3111ae
7 changed files with 195 additions and 5 deletions

View File

@@ -6,6 +6,7 @@ import com.aiosman.riderpro.data.api.GoogleRegisterRequestBody
import com.aiosman.riderpro.data.api.LoginUserRequestBody
import com.aiosman.riderpro.data.api.RegisterMessageChannelRequestBody
import com.aiosman.riderpro.data.api.RegisterRequestBody
import com.aiosman.riderpro.data.api.ResetPasswordRequestBody
import com.aiosman.riderpro.data.api.UpdateNoticeRequestBody
import com.aiosman.riderpro.entity.AccountFavouriteEntity
import com.aiosman.riderpro.entity.AccountLikeEntity
@@ -339,6 +340,9 @@ interface AccountService {
suspend fun updateNotice(payload: UpdateNoticeRequestBody)
suspend fun registerMessageChannel(client: String, identifier: String)
suspend fun resetPassword(email: String)
}
class AccountServiceImpl : AccountService {
@@ -455,4 +459,12 @@ class AccountServiceImpl : AccountService {
ApiClient.api.registerMessageChannel(RegisterMessageChannelRequestBody(client, identifier))
}
override suspend fun resetPassword(email: String) {
ApiClient.api.resetPassword(
ResetPasswordRequestBody(
username = email
)
)
}
}

View File

@@ -4,7 +4,6 @@ import android.icu.text.SimpleDateFormat
import android.icu.util.TimeZone
import com.aiosman.riderpro.AppStore
import com.aiosman.riderpro.ConstVars
import com.aiosman.riderpro.data.ServiceException
import com.auth0.android.jwt.JWT
import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor

View File

@@ -92,7 +92,10 @@ data class RegisterMessageChannelRequestBody(
@SerializedName("identifier")
val identifier: String,
)
data class ResetPasswordRequestBody(
@SerializedName("username")
val username: String,
)
interface RiderProAPI {
@POST("register")
suspend fun register(@Body body: RegisterRequestBody): Response<Unit>
@@ -270,4 +273,8 @@ interface RiderProAPI {
@Path("id") id: Int
): Response<Unit>
@POST("account/my/password/reset")
suspend fun resetPassword(
@Body body: ResetPasswordRequestBody
): Response<Unit>
}

View File

@@ -28,6 +28,7 @@ import com.aiosman.riderpro.LocalAnimatedContentScope
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.LocalSharedTransitionScope
import com.aiosman.riderpro.ui.account.AccountEditScreen2
import com.aiosman.riderpro.ui.account.ResetPasswordScreen
import com.aiosman.riderpro.ui.comment.CommentsScreen
import com.aiosman.riderpro.ui.favourite.FavouriteNoticeScreen
import com.aiosman.riderpro.ui.follower.FollowerListScreen
@@ -80,6 +81,7 @@ sealed class NavigationRoute(
data object Search : NavigationRoute("Search")
data object FollowerList : NavigationRoute("FollowerList/{id}")
data object FollowingList : NavigationRoute("FollowingList/{id}")
data object ResetPassword : NavigationRoute("ResetPassword")
}
@@ -262,6 +264,13 @@ fun NavigationController(
FollowingListScreen(it.arguments?.getInt("id")!!)
}
}
composable(route = NavigationRoute.ResetPassword.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
ResetPasswordScreen()
}
}
}

View File

@@ -0,0 +1,160 @@
package com.aiosman.riderpro.ui.account
import android.widget.Toast
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
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
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R
import com.aiosman.riderpro.data.AccountService
import com.aiosman.riderpro.data.AccountServiceImpl
import com.aiosman.riderpro.ui.comment.NoticeScreenHeader
import com.aiosman.riderpro.ui.composables.ActionButton
import com.aiosman.riderpro.ui.composables.StatusBarSpacer
import com.aiosman.riderpro.ui.composables.TextInputField
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import kotlinx.coroutines.launch
@Composable
fun ResetPasswordScreen() {
var username by remember { mutableStateOf("") }
val accountService: AccountService = AccountServiceImpl()
val scope = rememberCoroutineScope()
val context = LocalContext.current
var isSendSuccess by remember { mutableStateOf<Boolean?>(null) }
var isLoading by remember { mutableStateOf(false) }
val navController = LocalNavController.current
fun resetPassword() {
scope.launch {
isLoading = true
try {
accountService.resetPassword(username)
isSendSuccess = true
} catch (e: Exception) {
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
isSendSuccess = false
} finally {
isLoading = false
}
}
}
Column(
modifier = Modifier.fillMaxSize()
) {
StatusBarSpacer()
Box(
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
top = 16.dp,
bottom = 0.dp
)
) {
NoticeScreenHeader(
"RECOVER ACCOUNT",
moreIcon = false
)
}
Column(
modifier = Modifier.padding(horizontal = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(36.dp))
if (isSendSuccess != null) {
if (isSendSuccess!!) {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Reset password email has been sent to your email address",
style = TextStyle(
color = Color(0xFF333333),
fontSize = 14.sp,
fontWeight = FontWeight.Bold
)
)
} else {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Failed to send reset password email",
style = TextStyle(
color = Color(0xFF333333),
fontSize = 14.sp,
fontWeight = FontWeight.Bold
)
)
}
Spacer(modifier = Modifier.height(40.dp))
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.noRippleClickable {
navController.popBackStack()
}
) {
Image(
painter = painterResource(id = R.drawable.rider_pro_nav_back),
contentDescription = "Back",
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
androidx.compose.material3.Text(
stringResource(R.string.back_upper),
color = Color.Black,
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
}
} else {
Spacer(modifier = Modifier.height(120.dp))
TextInputField(
text = username,
onValueChange = { username = it },
label = stringResource(R.string.login_email_label),
hint = stringResource(R.string.text_hint_email),
enabled = !isLoading
)
Spacer(modifier = Modifier.height(72.dp))
if (isLoading) {
CircularProgressIndicator()
} else {
ActionButton(
modifier = Modifier
.width(345.dp)
.height(48.dp),
text = "Recover Account",
backgroundImage = R.mipmap.rider_pro_signup_red_bg
) {
resetPassword()
}
}
}
}
}
}

View File

@@ -43,7 +43,8 @@ fun TextInputField(
password: Boolean = false,
label: String? = null,
hint: String? = null,
error: String? = null
error: String? = null,
enabled: Boolean = true
) {
var showPassword by remember { mutableStateOf(!password) }
var isFocused by remember { mutableStateOf(false) }
@@ -74,6 +75,7 @@ fun TextInputField(
),
visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(),
singleLine = true,
enabled = enabled
)
if (password) {
Image(

View File

@@ -197,7 +197,9 @@ fun UserAuthScreen() {
fontSize = 12.sp
)
Spacer(modifier = Modifier.weight(1f))
Text(stringResource(R.string.forgot_password), fontSize = 12.sp)
Text(stringResource(R.string.forgot_password), fontSize = 12.sp, modifier = Modifier.noRippleClickable {
navController.navigate(NavigationRoute.ResetPassword.route)
})
}
}
Spacer(modifier = Modifier.height(64.dp))
@@ -210,7 +212,6 @@ fun UserAuthScreen() {
) {
onLogin()
}
Spacer(modifier = Modifier.height(48.dp))
Text(stringResource(R.string.or_login_with), color = Color(0xFF999999))
Spacer(modifier = Modifier.height(16.dp))