From db963809e2d62684ddb3d242204f82b4013428e0 Mon Sep 17 00:00:00 2001 From: panqihua <1029559041@qq.com> Date: Wed, 1 Apr 2020 02:50:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=87=8D=E7=BD=AE=E5=AF=86?= =?UTF-8?q?=E7=A0=81UI=E8=A1=A8=E5=8D=95=E6=A0=A1=E9=AA=8C=E3=80=81?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/.gitignore | 1 + app/my.key | Bin 0 -> 2230 bytes .../pocket/data/register/RegisterRequest.java | 2 + .../pocket/data/resetpwd/ResetPwdRequest.java | 51 ++++++ .../pocket/ui/login/LoginActivity.java | 2 +- .../pocket/ui/login/LoginViewModel.java | 18 +-- .../pocket/ui/register/RegisterActivity.java | 6 +- .../pocket/ui/register/RegisterViewModel.java | 31 +--- .../pocket/ui/resetpwd/ResetPwdFormState.java | 111 +++++++++++++ .../pocket/ui/resetpwd/ResetPwdResult.java | 33 ++++ .../pocket/ui/resetpwd/ResetPwdStep1.java | 105 ++++++++++++- .../pocket/ui/resetpwd/ResetPwdStep2.java | 115 +++++++++++++- .../pocket/ui/resetpwd/ResetPwdStep3.java | 96 +++++++++++- .../pocket/ui/resetpwd/ResetPwdViewModel.java | 148 ++++++++++++++++++ .../ui/resetpwd/ResetPwdViewModelFactory.java | 20 +++ .../java/com/community/pocket/util/Param.java | 9 ++ .../com/community/pocket/util/Result.java | 20 +++ .../com/community/pocket/util/ValidUtil.java | 46 ++++++ app/src/main/res/layout/activity_register.xml | 1 + .../main/res/layout/resetpwd/layout/step1.xml | 6 +- .../main/res/layout/resetpwd/layout/step2.xml | 28 ++-- .../main/res/layout/resetpwd/layout/step3.xml | 6 +- app/src/main/res/values-en-rUS/strings.xml | 11 ++ app/src/main/res/values-zh-rCN/strings.xml | 11 ++ app/src/main/res/values/strings.xml | 11 ++ 25 files changed, 819 insertions(+), 69 deletions(-) create mode 100644 app/my.key create mode 100644 app/src/main/java/com/community/pocket/data/resetpwd/ResetPwdRequest.java create mode 100644 app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdFormState.java create mode 100644 app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdResult.java create mode 100644 app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModel.java create mode 100644 app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModelFactory.java create mode 100644 app/src/main/java/com/community/pocket/util/Param.java create mode 100644 app/src/main/java/com/community/pocket/util/Result.java create mode 100644 app/src/main/java/com/community/pocket/util/ValidUtil.java diff --git a/app/.gitignore b/app/.gitignore index 796b96d..dc5ca96 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,2 @@ /build +/release/ diff --git a/app/my.key b/app/my.key new file mode 100644 index 0000000000000000000000000000000000000000..5d83e2932e5bd27974e647ea196c01ac7cbc39fc GIT binary patch literal 2230 zcmchY`8N~_AI4`T!%zr?K_gtf7+cqRnMTam!q`PjW|D12A%qwbCi`+rcF7>Sga*wu zgo(1mTh?5ab(Cd<((822J?EbOfcJ;zhv)OtbDr~@@AqKsU=08OfDQ%xDTp629Cc`d z)He5K001ZmMTH!o1bJX*cz_U~GUyl(2n9f>kmYZo=wa3O_VfgIStzXTG*T#(KD?4I%%kM#jO7isu1Ahnngxm33g(?3#stFqI@ocwbDsc zeB)6-PL71iT0XvfdMA_CZ^pm_g_AO;;>M?SKjd8_KEizmQ|N-_`GV@r2Yw?P1}>~b zw7yG*{)5S($u)8w*`e)_IWv4iVlBel%80hTCCiQ;a1geoUgNvEKqBS;RgA7 zXNUT?mD!vs6-7j}ouoL8$;vIU)0c+-SkEyPSE+w#Csgu|VanGKb^mG7!x1T6w~*?- ztQBG$HCtmp_9MJ+V~4z7&z^p)e`}v_(|+EXKMhlr^dclD7(t`jQbjUM7~@x$kW4Oa zDd_cEB{?N=?U6~Ke62cVBbG#8;dBKZK_K$!Uv}D)yNf#bI-B;`1LnBa;!`6mHStfU z%URs3vEA~Qn$o^MdqlSp7UeY*dn7+^bs8w45vmf)o~OsQN@O}t=}ioNYJ9g+u;2)9 z{q{B4XF8@?X{S}^39@sdSAU`}WE8e266j!R?U}f28`AH4&bu)^Ho@Q!c_v zy&UQOA;F>-kRjmFV>AUj7DOAc_AQZA->*CbI9b&3{=2ZCmdg+0vr|NLCv*Kp z&jAlR(kaSo5Lc4wCgtBs_}<^H=^pyRvsoBMQlxZ-*fh%;&%(!;^7Mnai$9LIzJYxq zQ^HSag^Y!c^AI@n~wdf{jfTSvA@Q&=bjk9dJ5>ZBawBilCo2>8t(wqV6&L{JR_e{Y zI{E+-f1boJYYs*CWLK2O)Q*;U<#`^sjYiw=w_A;7epA0MruOLNs+WsTuGY(f**NK0 z*w#9(O@>YY6;)fQ;eJo2DGrF~dxT}6^ww3C!)VnLA%mxXa3{VtDJ-x4b$kH3ozUSe zH^y4&?-N{oDww5kouW1pX{Iky z+KdD2Hrqi)=&k5BeQ{mJ;^UOLfS_$Yg79TQAxUL2t=1u(fUF#QR{w2uHzJUY%)u^3 zU+X)?J0%c4B-*V#_QWV^26z)WlcKDGvAEx3#^hl~%gwkQuW^tJyeL+irRZI)!lka> zEac%hPx!Wt2sw~-pC>QZztx{qWxzh>CXoeG)=CRZ+0Ryg-bJXhsy0d&005IwRIne4 z3c?qIK|l})B3mUhhl2C)DJNhPcHlrDKNNr>sS6z*|I>{vD zq<7f$LI(J;84EP+rxnckqoxKQ2H%Kdf-VN-kFH*E#KIhpN#%w!jqp1uSDoByvj_8M zXR7T}Zk@U7qLzQxBcyKJv_W!@g-TCH(MLP zLo8K8lt?68_I}#I{aZLZ{7Zp@%0!Oe|}ee+dC=nAkH5a)w{i6 zej^xnCT9_#n$W~+iLYE%-Hzbk3C53!6~t`HWJ;#ffW{inFx{H(5+4DSo~1hQHxRX*?)IxH^UskPQ`9-|PS%_*YeT#w3Ol=jTg z*e8aG?@#!#Dao3_TZSpUZ+5|H({%=E*jG2+Y85(J>gzap)V=O#=7e8bYYvQR( Ti1e-q+v(#qyCas%m3jXI4u;GJ literal 0 HcmV?d00001 diff --git a/app/src/main/java/com/community/pocket/data/register/RegisterRequest.java b/app/src/main/java/com/community/pocket/data/register/RegisterRequest.java index 315a4f4..e7f8fe4 100644 --- a/app/src/main/java/com/community/pocket/data/register/RegisterRequest.java +++ b/app/src/main/java/com/community/pocket/data/register/RegisterRequest.java @@ -8,6 +8,8 @@ import com.community.pocket.util.Valid; public class RegisterRequest { private static volatile RegisterRequest instance; + private RegisterRequest() { + } public static RegisterRequest getInstance() { if (instance == null) { diff --git a/app/src/main/java/com/community/pocket/data/resetpwd/ResetPwdRequest.java b/app/src/main/java/com/community/pocket/data/resetpwd/ResetPwdRequest.java new file mode 100644 index 0000000..eb13d18 --- /dev/null +++ b/app/src/main/java/com/community/pocket/data/resetpwd/ResetPwdRequest.java @@ -0,0 +1,51 @@ +package com.community.pocket.data.resetpwd; + +import com.community.pocket.util.Result; +import com.community.pocket.util.Valid; + +/** + * 重置密码请求 + * TODO 接口请求逻辑完善 + */ +public class ResetPwdRequest { + private static volatile ResetPwdRequest instance; + + private ResetPwdRequest() { + } + + public static ResetPwdRequest getInstance() { + if (instance == null) { + instance = new ResetPwdRequest(); + } + return instance; + } + + /** + * 检查用户邮箱 + */ + public Result checkUser(String username, String email) { + return new Result<>(Valid.ok, null); + } + + + /** + * 发送验证码 + */ + public Result sendCode(String username, String email) { + return new Result<>(Valid.ok, null); + } + + /** + * 检查验证码 + */ + public Result checkCode(String username, String email, String code) { + return new Result<>(Valid.ok, null); + } + + /** + * 重置密码 + */ + public Result resetPwd(String username, String password) { + return new Result<>(Valid.ok, null); + } +} diff --git a/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java b/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java index 8c46c16..ab84a75 100644 --- a/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java +++ b/app/src/main/java/com/community/pocket/ui/login/LoginActivity.java @@ -47,7 +47,7 @@ public class LoginActivity extends BaseActivity { private EditText passwordEditText; //登录按钮 - @ViewInject(R.id.back) + @ViewInject(R.id.login) private Button loginButton; //进度条 diff --git a/app/src/main/java/com/community/pocket/ui/login/LoginViewModel.java b/app/src/main/java/com/community/pocket/ui/login/LoginViewModel.java index bcf6d83..37cf89f 100644 --- a/app/src/main/java/com/community/pocket/ui/login/LoginViewModel.java +++ b/app/src/main/java/com/community/pocket/ui/login/LoginViewModel.java @@ -8,7 +8,7 @@ import com.community.pocket.R; import com.community.pocket.data.login.LoginRepository; import com.community.pocket.data.login.Result; import com.community.pocket.data.model.LoggedInUser; -import com.community.pocket.util.PropertiesUtil; +import com.community.pocket.util.ValidUtil; /** * 管理 登陆UI 相关数据 @@ -49,24 +49,12 @@ public class LoginViewModel extends ViewModel { //登陆表单数据变化触发数据校验 void loginDataChanged(String username, String password) { - if (!isUserNameValid(username)) { + if (!ValidUtil.usernamevalid(username)) { loginFormState.setValue(new LoginFormState(R.string.invalid_username, null)); - } else if (!isPasswordValid(password)) { + } else if (!ValidUtil.passwordvalid(password)) { loginFormState.setValue(new LoginFormState(null, R.string.invalid_password)); } else { loginFormState.setValue(new LoginFormState(true)); } } - - // A placeholder username validation check - //用户名校验 - private boolean isUserNameValid(String username) { - return username != null && username.trim().length() > PropertiesUtil.getIntValue("username.length"); - } - - // A placeholder password validation check - //密码校验 - private boolean isPasswordValid(String password) { - return password != null && password.trim().length() > PropertiesUtil.getIntValue("password.length"); - } } diff --git a/app/src/main/java/com/community/pocket/ui/register/RegisterActivity.java b/app/src/main/java/com/community/pocket/ui/register/RegisterActivity.java index 0e5d56a..559eb6a 100644 --- a/app/src/main/java/com/community/pocket/ui/register/RegisterActivity.java +++ b/app/src/main/java/com/community/pocket/ui/register/RegisterActivity.java @@ -128,13 +128,13 @@ public class RegisterActivity extends BaseActivity { } if (registerResult.getSuccess() != null) { Toast.makeText(getApplicationContext(), R.string.register_ok, Toast.LENGTH_SHORT).show(); + startActivity(new Intent(getApplicationContext(), LoginActivity.class)); + //Complete and destroy login activity once successful + finish(); } setResult(Activity.RESULT_OK); - startActivity(new Intent(getApplicationContext(), LoginActivity.class)); - //Complete and destroy login activity once successful - finish(); } }); diff --git a/app/src/main/java/com/community/pocket/ui/register/RegisterViewModel.java b/app/src/main/java/com/community/pocket/ui/register/RegisterViewModel.java index f8a2798..4992328 100644 --- a/app/src/main/java/com/community/pocket/ui/register/RegisterViewModel.java +++ b/app/src/main/java/com/community/pocket/ui/register/RegisterViewModel.java @@ -1,16 +1,12 @@ package com.community.pocket.ui.register; -import android.util.Patterns; - import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import com.community.pocket.R; import com.community.pocket.data.register.RegisterRequest; -import com.community.pocket.util.PropertiesUtil; import com.community.pocket.util.Valid; - -import java.util.regex.Pattern; +import com.community.pocket.util.ValidUtil; /** * 管理注册UI相关数据 @@ -49,38 +45,23 @@ class RegisterViewModel extends ViewModel { //监听注册表单数据变化触发数据校验 void registerDataChanged(String username, String password, String confirmPassword, String mobilePhone, String email) { - if (!usernamevalid(username)) { + if (!ValidUtil.usernamevalid(username)) { registerFormState.setValue(new RegisterFormState(R.string.invalid_username, null, null, null, null)); - } else if (!passwordvalid(password)) { + } else if (!ValidUtil.passwordvalid(password)) { registerFormState.setValue(new RegisterFormState(null, R.string.invalid_password, null, null, null)); - } else if (!passwordvalid(confirmPassword)) { + } else if (!ValidUtil.passwordvalid(confirmPassword)) { registerFormState.setValue(new RegisterFormState(null, null, R.string.invalid_password, null, null)); } else if (!confirmPassword.equals(password)) { registerFormState.setValue(new RegisterFormState(null, null, R.string.invalid_confirm_password, null, null)); - } else if (!mobilePhoneValid(mobilePhone)) { + } else if (!ValidUtil.mobilePhoneValid(mobilePhone)) { registerFormState.setValue(new RegisterFormState(null, null, null, R.string.invalid_mobiephone, null)); - } else if (!emailValid(email)) { + } else if (!ValidUtil.emailValid(email)) { registerFormState.setValue(new RegisterFormState(null, null, null, null, R.string.invalid_email)); } else { registerFormState.setValue(new RegisterFormState(true)); } } - private boolean emailValid(String email) { - return Patterns.EMAIL_ADDRESS.matcher(email).matches(); - } - - private boolean mobilePhoneValid(String mobilePhone) { - return Pattern.compile("^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$").matcher(mobilePhone).matches(); - } - - private boolean passwordvalid(String password) { - return password != null && password.trim().length() > PropertiesUtil.getIntValue("password.length"); - } - - private boolean usernamevalid(String username) { - return username != null && username.trim().length() > PropertiesUtil.getIntValue("username.length"); - } } diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdFormState.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdFormState.java new file mode 100644 index 0000000..d6ebdf1 --- /dev/null +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdFormState.java @@ -0,0 +1,111 @@ +package com.community.pocket.ui.resetpwd; + +import androidx.annotation.Nullable; + +class ResetPwdFormState { + /** + * 重置密码第一步校验 + */ + static class Step1 { + @Nullable + private Integer usernameError; + @Nullable + private Integer emailError; + + private boolean isDataValid; + + Step1(@Nullable Integer usernameError, @Nullable Integer emailError) { + this.usernameError = usernameError; + this.emailError = emailError; + } + + Step1(boolean isDataValid) { + this.isDataValid = isDataValid; + } + + @Nullable + Integer getUsernameError() { + return usernameError; + } + + @Nullable + Integer getEmailError() { + return emailError; + } + + boolean isDataValid() { + return isDataValid; + } + } + + /** + * 重置密码第二步校验 + */ + static class Step2 { + @Nullable + private Integer codeError; + //发送验证码剩余等待秒数 + private Integer second; + + private boolean isDataValid; + + Step2(@Nullable Integer codeError) { + this.codeError = codeError; + } + + Step2(@Nullable Integer codeError, Integer second) { + this.codeError = codeError; + this.second = second; + } + + Step2(boolean isDataValid) { + this.isDataValid = isDataValid; + } + + Integer getSecond() { + return second; + } + + @Nullable + Integer getCodeError() { + return codeError; + } + + boolean isDataValid() { + return isDataValid; + } + } + + static class Step3 { + @Nullable + private Integer passwordError; + @Nullable + private Integer confirmPasswordError; + + private boolean isDataValid; + + Step3(@Nullable Integer passwordError, @Nullable Integer confirmPasswordError) { + this.passwordError = passwordError; + this.confirmPasswordError = confirmPasswordError; + } + + Step3(boolean isDataValid) { + this.isDataValid = isDataValid; + } + + @Nullable + Integer getPasswordError() { + return passwordError; + } + + @Nullable + Integer getConfirmPasswordError() { + return confirmPasswordError; + } + + boolean isDataValid() { + return isDataValid; + } + } + +} diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdResult.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdResult.java new file mode 100644 index 0000000..7d5fd0c --- /dev/null +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdResult.java @@ -0,0 +1,33 @@ +package com.community.pocket.ui.resetpwd; + +import androidx.annotation.Nullable; + +/** + * 重置密码结果 + */ +class ResetPwdResult { + @Nullable + private Integer success; + @Nullable + private Integer error; + + @Nullable + Integer getSuccess() { + return success; + } + + ResetPwdResult setSuccess(@Nullable Integer success) { + this.success = success; + return this; + } + + @Nullable + Integer getError() { + return error; + } + + ResetPwdResult setError(@Nullable Integer error) { + this.error = error; + return this; + } +} diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep1.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep1.java index 89c864a..0415a13 100644 --- a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep1.java +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep1.java @@ -1,18 +1,32 @@ package com.community.pocket.ui.resetpwd; +import android.app.Activity; import android.content.Intent; import android.os.Build; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; import androidx.navigation.fragment.NavHostFragment; import com.community.pocket.R; import com.community.pocket.ui.BaseFragment; import com.community.pocket.ui.login.LoginActivity; +import com.community.pocket.util.Param; +import com.community.pocket.util.PropertiesUtil; import org.xutils.view.annotation.ContentView; import org.xutils.view.annotation.Event; +import org.xutils.view.annotation.ViewInject; import java.util.Objects; @@ -21,11 +35,98 @@ import java.util.Objects; */ @ContentView(R.layout.step1) public class ResetPwdStep1 extends BaseFragment { + + @ViewInject(R.id.username) + private EditText username; + + @ViewInject(R.id.email) + private EditText email; + + private ResetPwdViewModel resetPwdViewModel; + + @ViewInject(R.id.next) + private Button resetpwdButton; + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + resetPwdViewModel = new ViewModelProvider(this, new ResetPwdViewModelFactory()).get(ResetPwdViewModel.class); + //监听表单校验状态 + resetPwdViewModel.getResetPwdFormStep1().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(ResetPwdFormState.Step1 step1) { + if (step1 == null) { + return; + } + + resetpwdButton.setEnabled(step1.isDataValid()); + + if (step1.getUsernameError() != null) { + username.setError(getString(step1.getUsernameError(), PropertiesUtil.getIntValue("username.length"))); + } + if (step1.getEmailError() != null) { + email.setError(getString(step1.getEmailError(), PropertiesUtil.getIntValue("password.length"))); + } + } + }); + + //监听输入框文本 + TextWatcher afterTextChangedListener = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + resetPwdViewModel.resetpwdStep1Changed(username.getText().toString(), email.getText().toString()); + } + }; + + username.addTextChangedListener(afterTextChangedListener); + email.addTextChangedListener(afterTextChangedListener); + + //监听重置密码第一步请求 + resetPwdViewModel.getResetPwdResultStep1().observe(getViewLifecycleOwner(), new Observer() { + @RequiresApi(api = Build.VERSION_CODES.KITKAT) + @Override + public void onChanged(ResetPwdResult step1) { + if (step1 == null) { + return; + } + + if (step1.getError() != null) { + Toast.makeText(getContext(), step1.getError(), Toast.LENGTH_LONG).show(); + } + + if (step1.getSuccess() != null) { + Toast.makeText(getContext(), step1.getSuccess(), Toast.LENGTH_LONG).show(); + + Bundle bundle = new Bundle(); + bundle.putString(Param.username.name(), username.getText().toString()); + bundle.putString(Param.email.name(), email.getText().toString()); + + NavHostFragment.findNavController(ResetPwdStep1.this) + .navigate(R.id.action_First2Fragment_to_Second2Fragment, bundle); + } + + + Objects.requireNonNull(getActivity()).setResult(Activity.RESULT_OK); + } + }); + + } + //进入下一步发送验证码 @Event(value = R.id.next) private void onClick(View view) { - NavHostFragment.findNavController(ResetPwdStep1.this) - .navigate(R.id.action_First2Fragment_to_Second2Fragment); + resetPwdViewModel.checkUser(username.getText().toString(), email.getText().toString()); } //返回登陆 diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep2.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep2.java index 9d1cf45..d6e62a3 100644 --- a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep2.java +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep2.java @@ -1,15 +1,30 @@ package com.community.pocket.ui.resetpwd; +import android.os.Build; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; import android.view.View; +import android.widget.Button; +import android.widget.EditText; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; import androidx.navigation.fragment.NavHostFragment; import com.community.pocket.R; import com.community.pocket.ui.BaseFragment; +import com.community.pocket.util.Param; import org.xutils.view.annotation.ContentView; import org.xutils.view.annotation.Event; +import org.xutils.view.annotation.ViewInject; + +import java.util.Objects; /** * 重置密码第二步,发送验证码,输入 @@ -17,6 +32,26 @@ import org.xutils.view.annotation.Event; @ContentView(R.layout.step2) public class ResetPwdStep2 extends BaseFragment { + @ViewInject(R.id.username) + private EditText username; + + @ViewInject(R.id.email) + private EditText email; + + //验证码 + @ViewInject(R.id.code) + private EditText code; + + //发送验证码按钮 + @ViewInject(R.id.sendcode) + private Button sendCode; + + //下一步按钮 + @ViewInject(R.id.next) + private Button next; + + private ResetPwdViewModel resetPwdViewModel; + /** * 返回第一步输入账号邮箱 */ @@ -26,13 +61,87 @@ public class ResetPwdStep2 extends BaseFragment { .navigate(R.id.action_Second2Fragment_to_First2Fragment); } + @RequiresApi(api = Build.VERSION_CODES.KITKAT) + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + username.setText(Objects.requireNonNull(getArguments()).getString(Param.username.name())); + email.setText(Objects.requireNonNull(getArguments()).getString(Param.email.name())); + + resetPwdViewModel = new ViewModelProvider(this, new ResetPwdViewModelFactory()).get(ResetPwdViewModel.class); + + //监控表单数据校验状态 + resetPwdViewModel.getResetPwdFormStep2().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(ResetPwdFormState.Step2 step2) { + if (step2 == null) { + return; + } + + next.setEnabled(step2.isDataValid()); + + if (step2.getCodeError() != null) { + code.setError(getString(step2.getCodeError())); + } + + } + }); + + //监听输入框文本 + TextWatcher afterTextChangedListener = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + resetPwdViewModel.resetpwdStep2Changed(code.getText().toString()); + } + }; + code.addTextChangedListener(afterTextChangedListener); + + resetPwdViewModel.getResetPwdResultStep2().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(ResetPwdResult resetPwdResult) { + if (resetPwdResult == null) { + return; + } + + if (resetPwdResult.getSuccess() != null) { + Toast.makeText(getContext(), resetPwdResult.getSuccess(), Toast.LENGTH_LONG).show(); + if (resetPwdResult.getSuccess() == R.string.resetpwd_step2_ok) { + code.setEnabled(true); + } else { + Bundle bundle = new Bundle(); + bundle.putString(Param.username.name(), username.getText().toString()); + NavHostFragment.findNavController(ResetPwdStep2.this) + .navigate(R.id.action_Second2Fragment_to_threeFragment, bundle); + } + } + + if (resetPwdResult.getError() != null) { + Toast.makeText(getContext(), resetPwdResult.getError(), Toast.LENGTH_LONG).show(); + if (resetPwdResult.getError() == R.string.resetpwd_step2_fail) { + code.setEnabled(false); + } + } + } + }); + } + /** * 进入下一步重置密码 */ @Event(value = R.id.next) private void next(View view) { - NavHostFragment.findNavController(ResetPwdStep2.this) - .navigate(R.id.action_Second2Fragment_to_threeFragment); + resetPwdViewModel.checkCode(username.getText().toString(), email.getText().toString(), code.getText().toString()); } /** @@ -40,6 +149,6 @@ public class ResetPwdStep2 extends BaseFragment { */ @Event(value = R.id.sendcode) private void sendCode(View view) { - Toast.makeText(getContext(), R.string.action_sendcode, Toast.LENGTH_SHORT).show(); + resetPwdViewModel.sendCode(username.getText().toString(), email.getText().toString()); } } diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep3.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep3.java index 1d3387e..bc7b84b 100644 --- a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep3.java +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdStep3.java @@ -2,17 +2,29 @@ package com.community.pocket.ui.resetpwd; import android.content.Intent; import android.os.Build; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; import android.view.View; +import android.widget.Button; +import android.widget.EditText; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; import com.community.pocket.R; import com.community.pocket.ui.BaseFragment; import com.community.pocket.ui.login.LoginActivity; +import com.community.pocket.util.Param; +import com.community.pocket.util.PropertiesUtil; import org.xutils.view.annotation.ContentView; import org.xutils.view.annotation.Event; +import org.xutils.view.annotation.ViewInject; import java.util.Objects; @@ -22,9 +34,91 @@ import java.util.Objects; @ContentView(R.layout.step3) public class ResetPwdStep3 extends BaseFragment { + + //密码 + @ViewInject(R.id.password) + private EditText password; + + //确认密码 + @ViewInject(R.id.confirmPwd) + private EditText confirmPassword; + + //重置密码按钮 + @ViewInject(R.id.reset_pwd) + private Button resetpwdButton; + + private ResetPwdViewModel resetPwdViewModel; + + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + resetPwdViewModel = new ViewModelProvider(this, new ResetPwdViewModelFactory()).get(ResetPwdViewModel.class); + + //监听表单校验状态 + resetPwdViewModel.getResetPwdFormStep3().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(ResetPwdFormState.Step3 step3) { + if (step3 == null) { + return; + } + + if (step3.getPasswordError() != null) { + password.setError(getString(step3.getPasswordError(), PropertiesUtil.getIntValue("password.length"))); + } + + if (step3.getConfirmPasswordError() != null) { + confirmPassword.setError(getString(step3.getConfirmPasswordError(), PropertiesUtil.getIntValue("password.length"))); + } + + resetpwdButton.setEnabled(step3.isDataValid()); + } + }); + + TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + resetPwdViewModel.resetpwdStep3Changed(password.getText().toString(), confirmPassword.getText().toString()); + } + }; + + password.addTextChangedListener(textWatcher); + confirmPassword.addTextChangedListener(textWatcher); + + resetPwdViewModel.getResetPwdResultStep3().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(ResetPwdResult resetPwdResult) { + if (resetPwdResult == null) { + return; + } + + if (resetPwdResult.getSuccess() != null) { + Toast.makeText(getContext(), getString(R.string.resetpwd_step3_ok), Toast.LENGTH_LONG).show(); + startActivity(new Intent(getContext(), LoginActivity.class)); + + } + if (resetPwdResult.getError() != null) { + Toast.makeText(getContext(), getString(R.string.resetpwd_step3_fail), Toast.LENGTH_LONG).show(); + } + } + }); + } + + @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Event(value = R.id.reset_pwd) private void resetPwd(View v) { - Toast.makeText(getContext(), R.string.action_reset_password, Toast.LENGTH_SHORT).show(); + resetPwdViewModel.resetPwd(Objects.requireNonNull(getArguments()).getString(Param.username.name()), password.getText().toString()); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModel.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModel.java new file mode 100644 index 0000000..0545ddd --- /dev/null +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModel.java @@ -0,0 +1,148 @@ +package com.community.pocket.ui.resetpwd; + +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import com.community.pocket.R; +import com.community.pocket.data.resetpwd.ResetPwdRequest; +import com.community.pocket.util.Result; +import com.community.pocket.util.Valid; +import com.community.pocket.util.ValidUtil; + +/** + * 重置密码UI数据管理 + */ +class ResetPwdViewModel extends ViewModel { + + //重置密码第一步校验状态 + private MutableLiveData resetPwdFormStep1 = new MutableLiveData<>(); + //重置密码第一步验证结果 + private MutableLiveData resetPwdResultStep1 = new MutableLiveData<>(); + //重置密码第二步校验状态 + private MutableLiveData resetPwdFormStep2 = new MutableLiveData<>(); + //重置密码第二步发送验证码结果 + private MutableLiveData resetPwdResultStep2 = new MutableLiveData<>(); + //重置密码第三步校验状态 + private MutableLiveData resetPwdFormStep3 = new MutableLiveData<>(); + //重置密码第三部重置结果 + private MutableLiveData resetPwdResultStep3 = new MutableLiveData<>(); + + //重置密码请求 + private ResetPwdRequest resetPwdRequest; + + ResetPwdViewModel(ResetPwdRequest resetPwdRequest) { + this.resetPwdRequest = resetPwdRequest; + } + + MutableLiveData getResetPwdFormStep1() { + return resetPwdFormStep1; + } + + MutableLiveData getResetPwdResultStep1() { + return resetPwdResultStep1; + } + + MutableLiveData getResetPwdFormStep2() { + return resetPwdFormStep2; + } + + MutableLiveData getResetPwdResultStep2() { + return resetPwdResultStep2; + } + + MutableLiveData getResetPwdFormStep3() { + return resetPwdFormStep3; + } + + MutableLiveData getResetPwdResultStep3() { + return resetPwdResultStep3; + } + + //重置密码第一步 + void checkUser(String username, String email) { + Result result = resetPwdRequest.checkUser(username, email); + if (result.getValid() == Valid.ok) { + resetPwdResultStep1.setValue(new ResetPwdResult().setSuccess(R.string.resetpwd_step1_ok)); + } else { + resetPwdResultStep1.setValue(new ResetPwdResult().setError(R.string.resetpwd_step1_fail)); + } + } + + //重置密码第二步 + void sendCode(String username, String email) { + Result result = resetPwdRequest.sendCode(username, email); + if (result.getValid() == Valid.ok) { + resetPwdResultStep2.setValue(new ResetPwdResult().setSuccess(R.string.resetpwd_step2_ok)); + resetpwdStep2Changed(); + } else { + resetPwdResultStep2.setValue(new ResetPwdResult().setError(R.string.resetpwd_step2_fail)); + } + } + + //重置密码第二步 + void checkCode(String username, String email, String code) { + Result result = resetPwdRequest.checkCode(username, email, code); + if (result.getValid() == Valid.ok) { + resetPwdResultStep2.setValue(new ResetPwdResult().setSuccess(R.string.resetpwd_step2_valid_ok)); + } else { + resetPwdResultStep2.setValue(new ResetPwdResult().setError(R.string.resetpwd_step2_valid_fail)); + } + } + + //重置密码第三步 + void resetPwd(String username, String password) { + Result result = resetPwdRequest.resetPwd(username, password); + if (result.getValid() == Valid.ok) { + resetPwdResultStep3.setValue(new ResetPwdResult().setSuccess(R.string.resetpwd_step3_ok)); + } else { + resetPwdResultStep3.setValue(new ResetPwdResult().setError(R.string.resetpwd_step3_fail)); + } + } + + //监听重置密码第一步表单触发校验 + void resetpwdStep1Changed(String username, String email) { + if (!ValidUtil.usernamevalid(username)) { + resetPwdFormStep1.setValue(new ResetPwdFormState.Step1(R.string.invalid_username, null)); + } else if (!ValidUtil.emailValid(email)) { + resetPwdFormStep1.setValue(new ResetPwdFormState.Step1(null, R.string.invalid_email)); + } else { + resetPwdFormStep1.setValue(new ResetPwdFormState.Step1(true)); + } + } + + //TODO 异步更新验证码状态 + private void resetpwdStep2Changed() { +// int second=60; +// while (second-->0) { +// try { +// TimeUnit.SECONDS.sleep(1); +// resetPwdFormStep2.setValue(new ResetPwdFormState.Step2(R.string.invalid_send_CAPTCHA,second)); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// } + } + + //监听重置密码第二步表单触发校验 + void resetpwdStep2Changed(String code) { + if (!ValidUtil.CAPTCHAValid(code)) { + resetPwdFormStep2.setValue(new ResetPwdFormState.Step2(R.string.invalid_CAPTCHA)); + } else { + resetPwdFormStep2.setValue(new ResetPwdFormState.Step2(true)); + } + } + + //监听重置密码第三步表单触发校验 + void resetpwdStep3Changed(String password, String confirmPassword) { + if (!ValidUtil.passwordvalid(password)) { + resetPwdFormStep3.setValue(new ResetPwdFormState.Step3(R.string.invalid_password, null)); + } else if (!ValidUtil.passwordvalid(confirmPassword)) { + resetPwdFormStep3.setValue(new ResetPwdFormState.Step3(null, R.string.invalid_password)); + } else if (!password.equals(confirmPassword)) { + resetPwdFormStep3.setValue(new ResetPwdFormState.Step3(null, R.string.invalid_confirm_password)); + } else { + resetPwdFormStep3.setValue(new ResetPwdFormState.Step3(true)); + } + } + +} diff --git a/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModelFactory.java b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModelFactory.java new file mode 100644 index 0000000..6aa08c5 --- /dev/null +++ b/app/src/main/java/com/community/pocket/ui/resetpwd/ResetPwdViewModelFactory.java @@ -0,0 +1,20 @@ +package com.community.pocket.ui.resetpwd; + +import androidx.annotation.NonNull; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.community.pocket.data.resetpwd.ResetPwdRequest; + +public class ResetPwdViewModelFactory implements ViewModelProvider.Factory { + @NonNull + @Override + @SuppressWarnings("unchecked") + public T create(@NonNull Class modelClass) { + if (modelClass.isAssignableFrom(ResetPwdViewModel.class)) { + return (T) new ResetPwdViewModel(ResetPwdRequest.getInstance()); + } else { + throw new IllegalArgumentException("Unknown ViewModel class"); + } + } +} diff --git a/app/src/main/java/com/community/pocket/util/Param.java b/app/src/main/java/com/community/pocket/util/Param.java new file mode 100644 index 0000000..c9ebd6b --- /dev/null +++ b/app/src/main/java/com/community/pocket/util/Param.java @@ -0,0 +1,9 @@ +package com.community.pocket.util; + +/** + * 参数传递Key + */ +public enum Param { + username, + email +} diff --git a/app/src/main/java/com/community/pocket/util/Result.java b/app/src/main/java/com/community/pocket/util/Result.java new file mode 100644 index 0000000..6b45da7 --- /dev/null +++ b/app/src/main/java/com/community/pocket/util/Result.java @@ -0,0 +1,20 @@ +package com.community.pocket.util; + +public class Result { + private Valid valid; + + private T body; + + public Result(Valid valid, T body) { + this.valid = valid; + this.body = body; + } + + public Valid getValid() { + return valid; + } + + public T getBody() { + return body; + } +} diff --git a/app/src/main/java/com/community/pocket/util/ValidUtil.java b/app/src/main/java/com/community/pocket/util/ValidUtil.java new file mode 100644 index 0000000..7e8c12b --- /dev/null +++ b/app/src/main/java/com/community/pocket/util/ValidUtil.java @@ -0,0 +1,46 @@ +package com.community.pocket.util; + +import android.util.Patterns; + +import java.util.regex.Pattern; + +/** + * 表单校验工具类 + */ +public class ValidUtil { + + /** + * 校验邮箱 + */ + public static boolean emailValid(String email) { + return Patterns.EMAIL_ADDRESS.matcher(email).matches(); + } + + /** + * 校验手机号 + */ + public static boolean mobilePhoneValid(String mobilePhone) { + return Pattern.compile("^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$").matcher(mobilePhone).matches(); + } + + /** + * 校验密码 + */ + public static boolean passwordvalid(String password) { + return password != null && password.trim().length() > PropertiesUtil.getIntValue("password.length"); + } + + /** + * 校验用户名 + */ + public static boolean usernamevalid(String username) { + return username != null && username.trim().length() > PropertiesUtil.getIntValue("username.length"); + } + + /** + * 校验验证码 + */ + public static boolean CAPTCHAValid(String code) { + return Pattern.compile("^\\d{6}$").matcher(code).matches(); + } +} diff --git a/app/src/main/res/layout/activity_register.xml b/app/src/main/res/layout/activity_register.xml index ce78602..afdd7f6 100644 --- a/app/src/main/res/layout/activity_register.xml +++ b/app/src/main/res/layout/activity_register.xml @@ -104,6 +104,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/size_50" + android:enabled="false" android:text="@string/action_register" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/resetpwd/layout/step1.xml b/app/src/main/res/layout/resetpwd/layout/step1.xml index c564ee4..ed44798 100644 --- a/app/src/main/res/layout/resetpwd/layout/step1.xml +++ b/app/src/main/res/layout/resetpwd/layout/step1.xml @@ -10,9 +10,6 @@ android:id="@+id/username" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="24dp" - android:layout_marginTop="96dp" - android:layout_marginEnd="24dp" android:autofillHints="@string/AUTOFILL_HINT_USERNAME" android:hint="@string/prompt_user" @@ -26,10 +23,8 @@ android:id="@+id/email" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="24dp" android:layout_marginTop="8dp" - android:layout_marginEnd="24dp" android:autofillHints="@string/AUTOFILL_HINT_USERNAME" android:hint="@string/prompt_email" android:inputType="text|textEmailAddress" @@ -52,6 +47,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/size_50" + android:enabled="false" android:text="@string/next" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/resetpwd/layout/step2.xml b/app/src/main/res/layout/resetpwd/layout/step2.xml index a8eba41..09ea476 100644 --- a/app/src/main/res/layout/resetpwd/layout/step2.xml +++ b/app/src/main/res/layout/resetpwd/layout/step2.xml @@ -10,35 +10,44 @@ android:id="@+id/username" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="24dp" - android:layout_marginTop="96dp" - android:layout_marginEnd="24dp" android:autofillHints="@string/AUTOFILL_HINT_USERNAME" android:enabled="false" android:hint="@string/prompt_user" - android:inputType="text" android:selectAllOnFocus="true" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + tools:ignore="TextFields" /> + tools:layout_constraintTop_toBottomOf="@id/username" + tools:ignore="TextFields" /> + + + app:layout_constraintTop_toBottomOf="@id/code">