ModifyPwdPage.dart 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_habit/common/BaseArchitectural.dart';
  4. import 'package:flutter_habit/common/I18N.dart';
  5. import 'package:flutter_habit/provider/UserProvider.dart';
  6. import 'package:flutter_habit/common/utils/VerificationUtils.dart';
  7. import 'package:flutter_habit/network/Repository.dart';
  8. import 'package:provider/provider.dart';
  9. class ModifyPwdPage extends StatelessWidget {
  10. @override
  11. Widget build(BuildContext context) {
  12. return MultiProvider(
  13. providers: [
  14. ChangeNotifierProvider<ModifyPwdPageService>(
  15. create: (_) => ModifyPwdPageService(context)),
  16. ChangeNotifierProvider<ModifyPwdPageModel>(
  17. create: (_) => ModifyPwdPageModel(context)),
  18. ],
  19. child: _ModifyPwdPageView(),
  20. );
  21. }
  22. }
  23. // model
  24. class ModifyPwdPageModel extends BaseModel {
  25. ModifyPwdPageModel(BuildContext context) : super(context);
  26. late bool isRequesting;
  27. late bool isPwdVisible;
  28. int? counter;
  29. GlobalKey emailFormKey = GlobalKey<FormState>();
  30. GlobalKey pwdFormKey = GlobalKey<FormState>();
  31. TextEditingController? emailController;
  32. TextEditingController? authCodeController;
  33. TextEditingController? pwdController;
  34. TextEditingController? pwdRepeatController;
  35. Timer? timer;
  36. @override
  37. void init(BuildContext context) {
  38. super.init(context);
  39. isRequesting = false;
  40. isPwdVisible = false;
  41. counter = 0;
  42. emailFormKey = GlobalKey<FormState>();
  43. pwdFormKey = GlobalKey<FormState>();
  44. emailController = TextEditingController();
  45. emailController!.text =
  46. Provider.of<UserProvider>(context, listen: false).email ?? "";
  47. authCodeController = TextEditingController();
  48. pwdController = TextEditingController();
  49. pwdRepeatController = TextEditingController();
  50. timer = null;
  51. }
  52. @override
  53. void dispose() {
  54. super.dispose();
  55. if (timer != null) {
  56. timer!.cancel();
  57. }
  58. }
  59. }
  60. // service
  61. class ModifyPwdPageService extends BaseProvider {
  62. ModifyPwdPageService(BuildContext context) : super(context);
  63. String? validatorEmail(String? v) {
  64. if (VerifyUtils.isEmail(v)) {
  65. return null;
  66. } else {
  67. return I18N.of("邮箱格式有误");
  68. }
  69. }
  70. String? validatorPwd(String? v) {
  71. if (VerifyUtils.isPassword(v)) {
  72. return null;
  73. } else {
  74. return I18N.of("字母开头,必须包含大小写字母,可以包含字母、数字、特殊符号\n长度为8~16位");
  75. }
  76. }
  77. String? validatorPwdRepeat(BuildContext context) {
  78. ModifyPwdPageModel model =
  79. Provider.of<ModifyPwdPageModel>(context, listen: false);
  80. if (model.pwdController!.text == model.pwdRepeatController!.text) {
  81. return null;
  82. } else {
  83. return I18N.of("两次输入不一致");
  84. }
  85. }
  86. void pwdChangeVisible(BuildContext context) {
  87. ModifyPwdPageModel model =
  88. Provider.of<ModifyPwdPageModel>(context, listen: false);
  89. model.isPwdVisible = !model.isPwdVisible;
  90. model.refresh();
  91. }
  92. Future<void> sendAuthCode(BuildContext context) async {
  93. ModifyPwdPageModel model =
  94. Provider.of<ModifyPwdPageModel>(context, listen: false);
  95. model.isRequesting = true;
  96. model.refresh();
  97. if ((model.emailFormKey.currentState as FormState).validate()) {
  98. bool isSuccess = await Repository.getInstance()!.sendAuthCode(
  99. context,
  100. model.emailController!.text,
  101. "RESET_PWD",
  102. );
  103. if (isSuccess) {
  104. startCounter(context);
  105. }
  106. }
  107. model.isRequesting = false;
  108. model.refresh();
  109. }
  110. void startCounter(BuildContext context) {
  111. ModifyPwdPageModel model =
  112. Provider.of<ModifyPwdPageModel>(context, listen: false);
  113. model.counter = 60;
  114. model.refresh();
  115. model.timer = Timer.periodic(Duration(seconds: 1), (t) {
  116. model.counter--;
  117. model.refresh();
  118. if (model.counter == 0) {
  119. model.timer!.cancel();
  120. }
  121. });
  122. }
  123. Future<void> pwdReset(BuildContext context) async {
  124. ModifyPwdPageModel model =
  125. Provider.of<ModifyPwdPageModel>(context, listen: false);
  126. model.isRequesting = true;
  127. model.refresh();
  128. if ((model.pwdFormKey.currentState as FormState).validate()) {
  129. bool isSuccess = await Repository.getInstance()!.resetPwd(
  130. context,
  131. model.authCodeController!.text,
  132. model.emailController!.text,
  133. model.pwdController!.text,
  134. );
  135. if (isSuccess) {
  136. Navigator.of(context).pop(model.emailController!.text);
  137. }
  138. }
  139. model.isRequesting = false;
  140. model.refresh();
  141. }
  142. }
  143. // view
  144. class _ModifyPwdPageView extends StatelessWidget {
  145. @override
  146. Widget build(BuildContext context) {
  147. ModifyPwdPageService service =
  148. Provider.of<ModifyPwdPageService>(context, listen: false);
  149. ModifyPwdPageModel model =
  150. Provider.of<ModifyPwdPageModel>(context, listen: true);
  151. return Scaffold(
  152. appBar: AppBar(
  153. title: Text(I18N.of("重置密码")),
  154. ),
  155. body: Padding(
  156. padding: EdgeInsets.all(16),
  157. child: ListView(
  158. children: <Widget>[
  159. model.isRequesting ? LinearProgressIndicator() : Container(),
  160. Center(
  161. child: Icon(
  162. Icons.refresh,
  163. size: 220,
  164. color: Theme.of(context).unselectedWidgetColor,
  165. ),
  166. ),
  167. Form(
  168. key: model.emailFormKey,
  169. child: Column(
  170. children: <Widget>[
  171. TextFormField(
  172. controller: model.emailController,
  173. enabled: !model.isRequesting &&
  174. Provider.of<UserProvider>(context, listen: false)
  175. .token ==
  176. null,
  177. decoration: InputDecoration(
  178. labelText: I18N.of("邮箱"),
  179. hintText: I18N.of("请输入您注册时的邮箱"),
  180. prefixIcon: Icon(Icons.email),
  181. ),
  182. validator: (v) => service.validatorEmail(v),
  183. ),
  184. TextFormField(
  185. controller: model.authCodeController,
  186. enabled: !model.isRequesting,
  187. keyboardType: TextInputType.number,
  188. decoration: InputDecoration(
  189. labelText: I18N.of("验证码"),
  190. hintText: I18N.of("请输入6位验证码"),
  191. prefixIcon: Icon(Icons.security),
  192. suffixIcon: Padding(
  193. padding: EdgeInsets.only(top: 10),
  194. child: ElevatedButton(
  195. child: Text(
  196. I18N.of("获取验证码") +
  197. ((model.counter != 0)
  198. ? " ${model.counter}"
  199. : ""),
  200. style: TextStyle(
  201. color: Theme.of(context).cardColor,
  202. ),
  203. ),
  204. style: ButtonStyle(
  205. backgroundColor: MaterialStateProperty.all(
  206. Theme.of(context).colorScheme.secondary),
  207. shape: MaterialStateProperty.all(
  208. RoundedRectangleBorder(
  209. borderRadius: BorderRadius.circular(5.0),
  210. ))),
  211. onPressed: model.isRequesting || model.counter != 0
  212. ? null
  213. : () => service.sendAuthCode(context),
  214. ),
  215. ),
  216. ),
  217. ),
  218. ],
  219. ),
  220. ),
  221. Form(
  222. key: model.pwdFormKey,
  223. child: Column(
  224. children: <Widget>[
  225. TextFormField(
  226. controller: model.pwdController,
  227. enabled: !model.isRequesting,
  228. obscureText: !model.isPwdVisible,
  229. decoration: InputDecoration(
  230. labelText: I18N.of("新密码"),
  231. hintText: I18N.of("请输入您的新密码"),
  232. prefixIcon: Icon(Icons.lock_outline),
  233. suffixIcon: IconButton(
  234. icon: Icon(
  235. model.isPwdVisible
  236. ? Icons.visibility
  237. : Icons.visibility_off,
  238. ),
  239. onPressed: () => service.pwdChangeVisible(context),
  240. ),
  241. ),
  242. validator: (v) => service.validatorPwd(v),
  243. ),
  244. TextFormField(
  245. controller: model.pwdRepeatController,
  246. enabled: !model.isRequesting,
  247. obscureText: true,
  248. decoration: InputDecoration(
  249. labelText: I18N.of("重复密码"),
  250. hintText: I18N.of("请重复输入您的新密码"),
  251. prefixIcon: Icon(Icons.lock),
  252. ),
  253. validator: (v) => service.validatorPwdRepeat(context),
  254. ),
  255. ],
  256. ),
  257. ),
  258. Padding(
  259. padding: EdgeInsets.only(top: 10),
  260. child: ElevatedButton(
  261. child: Text(
  262. I18N.of("提交"),
  263. style: TextStyle(
  264. color: Theme.of(context).cardColor,
  265. ),
  266. ),
  267. style: ButtonStyle(
  268. backgroundColor: MaterialStateProperty.all(
  269. Theme.of(context).colorScheme.secondary),
  270. shape: MaterialStateProperty.all(RoundedRectangleBorder(
  271. borderRadius: BorderRadius.circular(5.0),
  272. ))),
  273. onPressed:
  274. model.isRequesting ? null : () => service.pwdReset(context),
  275. ),
  276. ),
  277. ],
  278. ),
  279. ),
  280. );
  281. }
  282. }