Commit 21621828e9bcdef1ed6534e3613f3ca1d4537f7a

Authored by 常守达
1 parent 32082e02

feat(email): 邮箱新绑定/换绑

@@ -116,5 +116,10 @@ class MyController extends GetxController { @@ -116,5 +116,10 @@ class MyController extends GetxController {
116 } 116 }
117 } 117 }
118 118
119 - void refreshEmail() {} 119 + Future<void> refreshEmail() async {
  120 + final result = await _userApi.getUserInfo();
  121 + if (result case AppSuccess<UserInfoResponse>(data: final user)) {
  122 + await Get.find<UserPreferencesStorage>().updateMeUserInfo(user);
  123 + }
  124 + }
120 } 125 }
@@ -43,6 +43,8 @@ class AddSecurityEmailController extends GetxController { @@ -43,6 +43,8 @@ class AddSecurityEmailController extends GetxController {
43 final confirmPasswordInput = ''.obs; 43 final confirmPasswordInput = ''.obs;
44 final isConfirmPasswordObscured = true.obs; 44 final isConfirmPasswordObscured = true.obs;
45 45
  46 + final isEmailExist = false.obs;
  47 +
46 @override 48 @override
47 void onInit() { 49 void onInit() {
48 super.onInit(); 50 super.onInit();
@@ -98,12 +100,18 @@ class AddSecurityEmailController extends GetxController { @@ -98,12 +100,18 @@ class AddSecurityEmailController extends GetxController {
98 if (!isEmailValid) return; 100 if (!isEmailValid) return;
99 try { 101 try {
100 await LoadingService.instance.run(() async { 102 await LoadingService.instance.run(() async {
101 - final result = await _userApi.requestEmailVerifyCode(emailInput.value);  
102 - // if (result is AppSuccess<void>) {  
103 - startResendCountdown();  
104 - Get.to(  
105 - () => SecurityEmailVerificationView(isChangeEmail: isChangeEmail));  
106 - // } 103 + final checkRsult = await _userApi.requestEmailCheck(emailInput.value);
  104 + if (checkRsult is AppSuccess<void>) {
  105 + final result =
  106 + await _userApi.requestEmailVerifyCode(emailInput.value);
  107 + if (result is AppSuccess<void>) {
  108 + startResendCountdown();
  109 + Get.to(() =>
  110 + SecurityEmailVerificationView(isChangeEmail: isChangeEmail));
  111 + }
  112 + } else {
  113 + isEmailExist.value = true;
  114 + }
107 }); 115 });
108 } catch (_) {} 116 } catch (_) {}
109 } 117 }
@@ -133,15 +141,18 @@ class AddSecurityEmailController extends GetxController { @@ -133,15 +141,18 @@ class AddSecurityEmailController extends GetxController {
133 codeController.text, 141 codeController.text,
134 ); 142 );
135 if (result is AppSuccess<void>) { 143 if (result is AppSuccess<void>) {
136 - AppToast.show(context.l10n.successChanged);  
137 - Get.back();  
138 - Get.back();  
139 - Get.back(); 144 + final changeEmailResult = await _userApi.changeEmail(
  145 + emailInput.value,
  146 + codeController.text,
  147 + );
  148 + if (changeEmailResult is AppSuccess<void>) {
  149 + AppToast.show(context.l10n.successChanged);
  150 + Get.back();
  151 + Get.back();
  152 + Get.back();
  153 + }
140 } else { 154 } else {
141 AppToast.show(context.l10n.verifyEmailFailed); 155 AppToast.show(context.l10n.verifyEmailFailed);
142 - Get.back();  
143 - Get.back();  
144 - Get.back();  
145 } 156 }
146 }); 157 });
147 } catch (_) {} 158 } catch (_) {}
@@ -152,11 +163,12 @@ class AddSecurityEmailController extends GetxController { @@ -152,11 +163,12 @@ class AddSecurityEmailController extends GetxController {
152 emailInput.value, 163 emailInput.value,
153 codeController.text, 164 codeController.text,
154 ); 165 );
155 - // if (result is AppSuccess<void>) {  
156 -  
157 - Get.to(() => const SetSecurityEmailPasswordView());  
158 -  
159 - // } 166 + if (result is AppSuccess<void>) {
  167 + AppToast.show(l10n.successChanged);
  168 + Get.to(() => const SetSecurityEmailPasswordView());
  169 + } else {
  170 + AppToast.show(l10n.verifyEmailFailed);
  171 + }
160 }); 172 });
161 } catch (_) {} 173 } catch (_) {}
162 } 174 }
@@ -174,16 +186,30 @@ class AddSecurityEmailController extends GetxController { @@ -174,16 +186,30 @@ class AddSecurityEmailController extends GetxController {
174 codeController.text, 186 codeController.text,
175 md5Password, 187 md5Password,
176 ); 188 );
177 - // if (result is AppSuccess<void>) {  
178 -  
179 - FocusScope.of(context).unfocus();  
180 - AppToast.show(context.l10n.settingsSaved);  
181 - TextInput.finishAutofillContext();  
182 - Get.back();  
183 - Get.back();  
184 - Get.back(); 189 + if (result is AppSuccess<void>) {
  190 + AppToast.show(context.l10n.settingsSaved);
  191 + FocusScope.of(context).unfocus();
  192 + AppToast.show(context.l10n.settingsSaved);
  193 + TextInput.finishAutofillContext();
  194 + Get.back();
  195 + Get.back();
  196 + Get.back();
  197 + } else {}
  198 + });
  199 + } catch (_) {}
  200 + }
185 201
186 - // } 202 + Future<void> verifyPassword() async {
  203 + try {
  204 + final md5Password =
  205 + md5.convert(utf8.encode(passwordInput.value)).toString();
  206 + await LoadingService.instance.run(() async {
  207 + final result = await _userApi.verifySefetyEmailPassword(
  208 + md5Password,
  209 + );
  210 + if (result is AppSuccess<void>) {
  211 + Get.to(() => AddSecurityEmailView(isChangeEmail: true));
  212 + } else {}
187 }); 213 });
188 } catch (_) {} 214 } catch (_) {}
189 } 215 }
@@ -153,7 +153,24 @@ class AddSecurityEmailView extends GetView<AddSecurityEmailController> { @@ -153,7 +153,24 @@ class AddSecurityEmailView extends GetView<AddSecurityEmailController> {
153 ), 153 ),
154 ); 154 );
155 }), 155 }),
156 - const SizedBox(height: 32), 156 + SizedBox(
  157 + height: 88,
  158 + child: Padding(
  159 + padding:
  160 + const EdgeInsets.only(top: 8.0, left: 20, right: 20),
  161 + child: Obx(() => controller.isEmailExist.value
  162 + ? Text(
  163 + 'This email is already linked to another account. Please use a different email.',
  164 + textAlign: TextAlign.center,
  165 + style: TextStyle(
  166 + color: context.colors.warning,
  167 + fontSize: 14,
  168 + fontWeight: FontWeight.w400,
  169 + ),
  170 + )
  171 + : SizedBox.shrink()),
  172 + ),
  173 + ),
157 SizedBox( 174 SizedBox(
158 width: double.infinity, 175 width: double.infinity,
159 height: 48, 176 height: 48,
@@ -814,7 +831,7 @@ class VerifyEmailPwdView extends GetView<AddSecurityEmailController> { @@ -814,7 +831,7 @@ class VerifyEmailPwdView extends GetView<AddSecurityEmailController> {
814 Obx(() { 831 Obx(() {
815 final isObscured = c.isPasswordObscured.value; 832 final isObscured = c.isPasswordObscured.value;
816 return TextField( 833 return TextField(
817 - textInputAction: TextInputAction.next, 834 + // textInputAction: TextInputAction.next,
818 controller: c.passwordController, 835 controller: c.passwordController,
819 // keyboardType: TextInputType.visiblePassword, 836 // keyboardType: TextInputType.visiblePassword,
820 obscureText: isObscured, 837 obscureText: isObscured,
@@ -889,8 +906,7 @@ class VerifyEmailPwdView extends GetView<AddSecurityEmailController> { @@ -889,8 +906,7 @@ class VerifyEmailPwdView extends GetView<AddSecurityEmailController> {
889 ), 906 ),
890 ), 907 ),
891 ), 908 ),
892 - onSubmitted: (_) =>  
893 - Get.to(() => AddSecurityEmailView(isChangeEmail: true)), 909 + onSubmitted: (_) => c.verifyPassword(),
894 ); 910 );
895 }), 911 }),
896 const SizedBox(height: 8), 912 const SizedBox(height: 8),
@@ -913,10 +929,8 @@ class VerifyEmailPwdView extends GetView<AddSecurityEmailController> { @@ -913,10 +929,8 @@ class VerifyEmailPwdView extends GetView<AddSecurityEmailController> {
913 height: 48, 929 height: 48,
914 child: Obx( 930 child: Obx(
915 () => ElevatedButton( 931 () => ElevatedButton(
916 - onPressed: c.isPasswordValid  
917 - ? () => Get.to(  
918 - () => AddSecurityEmailView(isChangeEmail: true))  
919 - : null, 932 + onPressed:
  933 + c.isPasswordValid ? () => c.verifyPassword() : null,
920 style: ElevatedButton.styleFrom( 934 style: ElevatedButton.styleFrom(
921 backgroundColor: colors.primary, 935 backgroundColor: colors.primary,
922 disabledBackgroundColor: 936 disabledBackgroundColor:
@@ -289,7 +289,20 @@ class UserApi { @@ -289,7 +289,20 @@ class UserApi {
289 await _dioClient.dio.post( 289 await _dioClient.dio.post(
290 ApiPaths.emailSendCode, 290 ApiPaths.emailSendCode,
291 data: { 291 data: {
292 - 'safety_email': email, 292 + 'email': email,
  293 + },
  294 + );
  295 + },
  296 + );
  297 + }
  298 +
  299 + Future<AppResult<void>> requestEmailCheck(String email) {
  300 + return safeCall(
  301 + call: () async {
  302 + await _dioClient.dio.post(
  303 + ApiPaths.emailCheck,
  304 + data: {
  305 + 'email': email,
293 }, 306 },
294 ); 307 );
295 }, 308 },
@@ -302,8 +315,22 @@ class UserApi { @@ -302,8 +315,22 @@ class UserApi {
302 await _dioClient.dio.post( 315 await _dioClient.dio.post(
303 ApiPaths.emailVerifyCode, 316 ApiPaths.emailVerifyCode,
304 data: { 317 data: {
305 - 'safety_email': email,  
306 - 'safety_email_code': code, 318 + 'email': email,
  319 + 'code': code,
  320 + },
  321 + );
  322 + },
  323 + );
  324 + }
  325 +
  326 + Future<AppResult<void>> changeEmail(String email, String code) {
  327 + return safeCall(
  328 + call: () async {
  329 + await _dioClient.dio.post(
  330 + ApiPaths.changeEmail,
  331 + data: {
  332 + 'email': email,
  333 + 'code': code,
307 }, 334 },
308 ); 335 );
309 }, 336 },
@@ -317,8 +344,22 @@ class UserApi { @@ -317,8 +344,22 @@ class UserApi {
317 await _dioClient.dio.post( 344 await _dioClient.dio.post(
318 ApiPaths.addSafetyEmail, 345 ApiPaths.addSafetyEmail,
319 data: { 346 data: {
320 - 'safety_email': email,  
321 - 'safety_email_code': code, 347 + 'email': email,
  348 + 'code': code,
  349 + 'password': pwd,
  350 + },
  351 + );
  352 + },
  353 + );
  354 + }
  355 +
  356 + Future<AppResult<void>> verifySefetyEmailPassword(String pwd) {
  357 + return safeCall(
  358 + call: () async {
  359 + await _dioClient.dio.post(
  360 + ApiPaths.changeEmailVerifyPassword,
  361 + data: {
  362 + 'current_password': pwd,
322 }, 363 },
323 ); 364 );
324 }, 365 },
@@ -4,11 +4,13 @@ abstract final class ApiPaths { @@ -4,11 +4,13 @@ abstract final class ApiPaths {
4 static const userRegister = '/client/doublefeel/user/register/'; 4 static const userRegister = '/client/doublefeel/user/register/';
5 static const userLogin = '/client/doublefeel/user/login/'; 5 static const userLogin = '/client/doublefeel/user/login/';
6 static const smsSendCode = '/client/doublefeel/sms/send_code/'; 6 static const smsSendCode = '/client/doublefeel/sms/send_code/';
7 - static const emailSendCode =  
8 - '/client/doublefeel/safety_email/send_verify_code/';  
9 - static const emailVerifyCode = '/client/doublefeel/safety_email/verify_code/';  
10 - static const addSafetyEmail =  
11 - '/client/doublefeel/safety_email/add_safety_email/'; 7 + static const emailCheck = '/client/doublefeel/user/email/check/';
  8 + static const emailSendCode = '/client/doublefeel/user/email/send_email/';
  9 + static const emailVerifyCode = '/client/doublefeel/user/email/check_code/';
  10 + static const changeEmail = '/client/doublefeel/user/email/change/';
  11 + static const addSafetyEmail = '/client/doublefeel/user/email/submit/';
  12 + static const changeEmailVerifyPassword =
  13 + '/client/doublefeel/user/email/change/verify_password/';
12 static const userPair = '/client/doublefeel/user/pair/'; 14 static const userPair = '/client/doublefeel/user/pair/';
13 static const userLogout = '/client/doublefeel/user/logout/'; 15 static const userLogout = '/client/doublefeel/user/logout/';
14 static const userDeleteAccount = '/client/doublefeel/user/account/delete/'; 16 static const userDeleteAccount = '/client/doublefeel/user/account/delete/';