package com.yingmao.clash.act import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.os.CountDownTimer import android.text.method.HideReturnsTransformationMethod import android.view.View import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import android.widget.* import androidx.appcompat.widget.AppCompatImageView import androidx.lifecycle.ViewModelProvider import com.cncat.vpn.service.ClashManager import com.cncat.vpn.service.remote.IClashManager import com.cncat.vpn.service.remote.wrap import com.google.gson.JsonObject import com.yingmao.clash.view.dialog.RxDialogShapeLoading import com.tencent.mmkv.MMKV import com.yingmao.clash.BuildConfig import com.yingmao.clash.R import com.yingmao.clash.app.MainApplication import com.yingmao.clash.base.BaseActivity import com.yingmao.clash.conf.BZYConstants import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.entity.GetSMSCodeRsp import com.yingmao.clash.net.http.entity.RegisterRsp import com.yingmao.clash.util.AESUtil import com.yingmao.clash.util.CommonUtils import com.yingmao.clash.util.Utils import com.yingmao.clash.view.PasswordTransformationMethodBigDot import com.yingmao.clash.view.RxToast class RegisterActivity : BaseActivity(), View.OnClickListener { private lateinit var usernameEt: EditText private lateinit var passwordEt: EditText private lateinit var passwordEtCheck: EditText private lateinit var username: String private lateinit var password: String private lateinit var passwordCheck: String private lateinit var tvSmSCode:TextView private lateinit var etSmSCode:EditText private lateinit var rxDialogShapeLoading: RxDialogShapeLoading private var phoneNumber: String = "" private lateinit var registerAtyVM: RegisterAtyVM private var countDownTimer: CountDownTimer? = null private var registerKey = "" private var registerIV2 = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_register) //点击输入框外边隐藏输入法 必须在setContentView之后调用 setupUI(findViewById(android.R.id.content).getChildAt(0)) initView() val clashBinder = MainApplication.getApp()?.let { ClashManager(it).wrap() as IClashManager } clashBinder?.let { cb -> val signList = AESUtil.getSingInfo(this@RegisterActivity, BuildConfig.applicationId, AESUtil.SHA256) if (signList.isNotEmpty()) { val si = signList[0] val ss1 = cb.getSS1(si) val ss2 = cb.getSS2(si) registerKey = cb.getRegisterKey(si) registerIV2 = cb.getRegisterKiv(si) com.cncat.vpn.common.log.Log.d("si==>${si}, ss1==>${ss1}, ss2==>${ss2}") MainApplication.KEY2 = ss1 MainApplication.IV2 = ss2 } } registerAtyVM = ViewModelProvider(this)[RegisterAtyVM::class.java] observe(this, registerAtyVM) // httpStatus(registerAtyVM) } override fun httpLoading(httpStatus: HttpStatus.Loading) { when(httpStatus.reqType){ HttpReqType.BaseREGISTER->{ rxDialogShapeLoading.setMessage("注册中...") rxDialogShapeLoading.show() } else->{ } } } override fun httpSuccess(httpStatus: HttpStatus.Success) { when(httpStatus.reqType){ HttpReqType.GETSMSCODE->{ (httpStatus.rsp as GetSMSCodeRsp).let { rsp -> if (rsp.code == 1000) { RxToast.success(resources.getString(R.string.VerificationCodeSent)) countDown() } else { RxToast.warning(resources.getString(R.string.VerificationCodeSentFail)+ rsp.message) } } } HttpReqType.BaseREGISTER->{ rxDialogShapeLoading.cancel() with(httpStatus.rsp as RegisterRsp) { if (code == "200") { RxToast.success("注册成功") if(httpStatus.rsp.data!=null){ username= httpStatus.rsp.data.phoneNumber.toString() MMKV.defaultMMKV() .encode(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, username) MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_IS_REGISTER, true) MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_NOTE_DEFAULT_PSW, true) startActivity(Intent(this@RegisterActivity, LoginActivity::class.java)) finish() } } else RxToast.error("注册失败:(${code})${message}") } } else->{ } } } override fun httpFailure(httpStatus: HttpStatus.Failure) { when(httpStatus.reqType) { HttpReqType.GETSMSCODE -> { rxDialogShapeLoading.cancel() RxToast.error("注册失败:${httpStatus.msg}") } HttpReqType.BaseREGISTER->{ rxDialogShapeLoading.cancel() RxToast.error("注册失败:${httpStatus.msg}") } else->{ } } } private fun initView() { usernameEt = findViewById(R.id.et_username) passwordEt = findViewById(R.id.et_password) passwordEtCheck = findViewById(R.id.et_password_check) passwordEt.transformationMethod = PasswordTransformationMethodBigDot() passwordEtCheck.transformationMethod = PasswordTransformationMethodBigDot() tvSmSCode=findViewById(R.id.tv_sms_code) etSmSCode=findViewById(R.id.et_sms_code) rxDialogShapeLoading = RxDialogShapeLoading(this) tvSmSCode.setOnClickListener { phoneNumber = usernameEt.text.trim().toString() if(Utils.isEmail(phoneNumber)||Utils.isPhoneNumber(phoneNumber)){ registerAtyVM.getSMSCode(phoneNumber) }else{ RxToast.warning(resources.getString(R.string.phoneOrEmail)) } } val passwordHideCb = findViewById(R.id.cb_password_hide) passwordHideCb.setOnCheckedChangeListener(IOnCheckedChangeListener()) val passwordHideCb2 = findViewById(R.id.cb_password_hide_check) passwordHideCb2.setOnCheckedChangeListener(IOnCheckedChangeListener()) val registerTv = findViewById(R.id.tv_register) registerTv.setOnClickListener(this) val loginTv = findViewById(R.id.tv_login) loginTv.setOnClickListener(this) } override fun onClick(v: View?) { when (v?.id) { R.id.tv_register -> { val smsCode =etSmSCode.text.trim().toString() if(smsCode.isEmpty()){ RxToast.error("验证码不能为空") return } if (checkInput()){ val reqJson = JsonObject() reqJson.addProperty("phoneNumber", username) reqJson.addProperty("password", password) reqJson.addProperty("password_check", passwordCheck) reqJson.addProperty("invitationCode", BuildConfig.productId) reqJson.addProperty("from", "5") reqJson.addProperty("androidDevice", Utils.getUniqueID(this)) reqJson.addProperty("smsCode", smsCode) if (registerKey.isNotEmpty() && registerIV2.isNotEmpty()) { val data = AESUtil.byteArrayToHexStr( AESUtil.RegisterEncrypt(reqJson.toString(), registerKey, registerIV2) ) val params: Map = mutableMapOf( "data" to data ) registerAtyVM.registerBySMSCode(params) } } } R.id.tv_login -> { val intent = Intent(this@RegisterActivity, LoginActivity::class.java) startActivity(intent) finish() } } } private fun checkInput(): Boolean { username = usernameEt.text.toString().trim() if (username.isBlank()) { getFocusAndShowSoftInput(usernameEt) return false } if (!CommonUtils.checkUsername(username)) { getFocusAndShowSoftInput(usernameEt) return false } password = passwordEt.text.toString().trim() if (password.isBlank()) { getFocusAndShowSoftInput(passwordEt) return false } passwordCheck = passwordEtCheck.text.toString().trim() if (password.isBlank()) { getFocusAndShowSoftInput(passwordEtCheck) return false } if (password != passwordCheck) { return false } return true } private fun getFocusAndShowSoftInput(editText: EditText) { editText.requestFocus() val imm: InputMethodManager = editText.context .getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED) } private inner class IOnCheckedChangeListener : CompoundButton.OnCheckedChangeListener { override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { when (buttonView?.id) { R.id.cb_password_hide -> { if (isChecked) passwordEt.transformationMethod = HideReturnsTransformationMethod.getInstance() else passwordEt.transformationMethod = PasswordTransformationMethodBigDot() } R.id.cb_password_hide_check -> { if (isChecked) passwordEtCheck.transformationMethod = HideReturnsTransformationMethod.getInstance() else passwordEtCheck.transformationMethod = PasswordTransformationMethodBigDot() } } } } private fun countDown() { tvSmSCode.isEnabled = false countDownTimer = object : CountDownTimer(60000, 1000) { override fun onFinish() { tvSmSCode.isEnabled = true tvSmSCode.text = resources.getString(R.string.ObtainVerificationCode) } @SuppressLint("SetTextI18n") override fun onTick(millisUntilFinished: Long) { tvSmSCode.text = "${millisUntilFinished / 1000} S" } }.start() } override fun onDestroy() { super.onDestroy() countDownTimer?.cancel() } }