Files
BirdsProject/app/src/main/java/com/juhabi/birds/login/LoginActivity.kt
2026-09-19 08:41:53 +08:00

216 lines
7.5 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.juhabi.birds.login
import android.content.Intent
import android.os.Bundle
import android.os.CountDownTimer
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import com.gyf.immersionbar.ImmersionBar
import com.juhabi.birds.AppConfig
import com.juhabi.birds.R
import com.juhabi.birds.base.BaseActivity
import com.juhabi.birds.databinding.ActivityLoginBinding
import com.juhabi.birds.login.model.UserEntity
import com.juhabi.birds.login.mvp.LoginContract
import com.juhabi.birds.login.mvp.LoginImpl
import com.juhabi.birds.login.mvp.LoginPresenter
import com.juhabi.birds.main.MainActivity
import com.juhabi.birds.mine.MineCenterActivity
import com.juhabi.birds.network.TokenManager
import com.juhabi.birds.util.SharedPreferencesUtil
import com.juhabi.birds.util.ToastUtil
/**
* 登录
*/
class LoginActivity : BaseActivity<ActivityLoginBinding, LoginPresenter>(),
LoginContract.LoginView, View.OnClickListener {
/** 是否使用密码登录;false 为手机号 + 验证码登录 */
private var loginByPassword = true
private var isPasswordVisible = false
private var codeCountDownTimer: CountDownTimer? = null
override fun createBinding(inflater: LayoutInflater): ActivityLoginBinding {
return ActivityLoginBinding.inflate(inflater)
}
override fun createPresenter(): LoginPresenter {
return LoginPresenter(LoginImpl())
}
override fun initWindows() {
ImmersionBar.with(this)
.navigationBarColor(R.color.color_zhu)
.navigationBarDarkIcon(true)
.init()
}
override fun initView(savedInstanceState: Bundle?) {
listOf(
binding.tvChangeCode,
binding.forgotPasswordButton,
binding.passwordVisibilityButton,
binding.getCodeButton,
binding.loginButton,
binding.registerButton,
).forEach { button ->
button.setOnClickListener(this)
}
}
override fun onClick(view: View) {
when (view.id) {
R.id.tvChangeCode -> {//更换登录方式
if (loginByPassword) {
binding.linearCode.visibility = View.VISIBLE
binding.linearPsd.visibility = View.GONE
loginByPassword = false
binding.tvChangeCode.setText(R.string.register_change_psd_login)
} else {
binding.linearCode.visibility = View.GONE
binding.linearPsd.visibility = View.VISIBLE
loginByPassword = true
binding.tvChangeCode.setText(R.string.register_change_code_login)
}
}
R.id.getCodeButton -> {//获取验证码
val phone = binding.accountEditText.text.toString().trim()
if (phone.isBlank()) {
ToastUtil.showShort(mContext, "手机号不能为空")
return
}
presenter?.getPhoneSmsCode(phone, AppConfig.SEND_CODE_SCENE_LOGIN)
}
R.id.registerButton -> {//注册
goTo(RegisterActivity::class.java, null)
}
R.id.forgotPasswordButton -> {//忘记密码
goTo(ForgetPsdActivity::class.java, null)
}
R.id.passwordVisibilityButton -> {
togglePasswordVisibility()
}
R.id.loginButton -> {//登录
val account = binding.accountEditText.text.toString().trim()
if (account.isBlank()) {
ToastUtil.showShort(mContext, "账号不能为空")
return
}
if (loginByPassword) {
val password = binding.passwordEditText.text.toString()
if (password.isBlank()) {
ToastUtil.showShort(mContext, "密码不能为空")
return
}
presenter?.loginByPhonePsd(account, password)
} else {
val code = binding.codeEditText.text.toString().trim()
if (code.isBlank()) {
ToastUtil.showShort(mContext, "验证码不能为空")
return
}
presenter?.loginByPhoneSms(account, code)
}
}
}
}
private fun togglePasswordVisibility() {
isPasswordVisible = !isPasswordVisible
val selection = binding.passwordEditText.selectionEnd
binding.passwordEditText.inputType = if (isPasswordVisible) {
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
} else {
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
}
// 保持光标位置,并触发 typeface 刷新
binding.passwordEditText.setSelection(selection.coerceAtLeast(0))
binding.passwordEditText.typeface = binding.accountEditText.typeface
}
override fun sendCodeSuccess(message: String) {
hideLoading()
ToastUtil.showShort(mContext, message)
codeCountDownTimer?.cancel()
binding.getCodeButton.apply {
isEnabled = false
isClickable = false
setBackgroundResource(R.drawable.shape_register_code_disabled_bg)
text = getString(R.string.register_code_countdown, CODE_COUNTDOWN_SECONDS)
}
codeCountDownTimer = object : CountDownTimer(CODE_COUNTDOWN_MILLIS, 1_000L) {
override fun onTick(millisUntilFinished: Long) {
val secondsRemaining = (millisUntilFinished + 999L) / 1_000L
binding.getCodeButton.text = getString(
R.string.register_code_countdown,
secondsRemaining
)
}
override fun onFinish() {
codeCountDownTimer = null
binding.getCodeButton.apply {
isEnabled = true
isClickable = true
setBackgroundResource(R.drawable.shape_register_code_bg)
setText(R.string.register_get_code)
}
}
}.start()
}
override fun onRegisterSuccess(message: String) {
}
override fun onForgetPsdSuccess(message: String) {
}
override fun showUsernameError(message: String) {
ToastUtil.showShort(mContext, message)
}
override fun showPasswordError(message: String) {
ToastUtil.showShort(mContext, message)
}
override fun clearInputErrors() {
}
override fun onLoginSuccess(user: UserEntity) {
val token = user.token.trim()
// SharedPreferences 持久化 token,并同步到内存 AppConfig.userToken
TokenManager.save(this, token)
AppConfig.USER_LOGIN = token.isNotBlank()
SharedPreferencesUtil.putBoolean(this, KEY_USER_LOGIN, AppConfig.USER_LOGIN)
ToastUtil.showShort(mContext, "登录成功")
startActivity(Intent(this, MainActivity::class.java))
finish()
}
override fun showError(message: String) {
hideLoading()
ToastUtil.showShort(mContext, message)
}
override fun onDestroy() {
codeCountDownTimer?.cancel()
codeCountDownTimer = null
super.onDestroy()
}
private companion object {
const val CODE_COUNTDOWN_SECONDS = 60L
const val CODE_COUNTDOWN_MILLIS = CODE_COUNTDOWN_SECONDS * 1_000L
const val KEY_USER_LOGIN = "user_login"
}
}