security_email_controller.dart 5.86 KB
import 'dart:async';
import 'dart:convert';

import 'package:crypto/crypto.dart';
import 'package:doublefeel_flutter/app/modules/home/widgets/my/security_email_views.dart';
import 'package:doublefeel_flutter/core/network/api/user_api.dart';
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/core/services/loading_service.dart';
import 'package:doublefeel_flutter/core/util/app_toast.dart';
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';

class AddSecurityEmailController extends GetxController {
  final UserApi _userApi = Get.find<UserApi>();
  final userPrefs = Get.find<UserPreferencesStorage>();
  static final _emailPattern = RegExp(
    r'^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$',
  );
  static const resendSeconds = 60;

  final emailController = TextEditingController();
  final codeController = TextEditingController();

  final hasSubmittedEmail = false.obs;
  final emailInput = ''.obs;
  final codeInput = ''.obs;
  final secondsRemaining = resendSeconds.obs;

  Timer? _resendTimer;

  static final _passwordRegex = RegExp(
    r'^(?=.*[0-9])(?=.*[A-Z]).{6,}$',
  );

  final passwordController = TextEditingController();
  final passwordInput = ''.obs;
  final isPasswordObscured = true.obs;

  final confirmPasswordController = TextEditingController();
  final confirmPasswordInput = ''.obs;
  final isConfirmPasswordObscured = true.obs;

  @override
  void onInit() {
    super.onInit();
    emailController.addListener(_onEmailChanged);
    codeController.addListener(_onCodeChanged);
    passwordController.addListener(_onPasswordChanged);
    confirmPasswordController.addListener(_onConfirmPasswordChanged);
  }

  void _onEmailChanged() {
    emailInput.value = emailController.text.replaceAll(' ', '').trim();
  }

  void _onCodeChanged() {
    codeInput.value = codeController.text.trim();
  }

  void _onPasswordChanged() {
    passwordInput.value = passwordController.text.trim();
  }

  void _onConfirmPasswordChanged() {
    confirmPasswordInput.value = confirmPasswordController.text.trim();
  }

  bool get isEmailValid => _emailPattern.hasMatch(emailInput.value);

  bool get isPasswordValid =>
      _passwordRegex.hasMatch(passwordInput.value) &&
      passwordInput.value.isNotEmpty;

  bool get isConfirmPasswordValid =>
      _passwordRegex.hasMatch(confirmPasswordInput.value) &&
      confirmPasswordInput.value.isNotEmpty &&
      confirmPasswordInput.value == passwordInput.value;

  bool get canSetPassword => isPasswordValid && isConfirmPasswordValid;

  bool get showError => hasSubmittedEmail.value && !isEmailValid;

  bool get canSubmitCode => codeInput.value.isNotEmpty;

  void togglePasswordVisibility() {
    isPasswordObscured.value = !isPasswordObscured.value;
  }

  void toggleConfirmPasswordVisibility() {
    isConfirmPasswordObscured.value = !isConfirmPasswordObscured.value;
  }

  Future<void> sendVerificationEmail({bool isChangeEmail = false}) async {
    hasSubmittedEmail.value = true;
    if (!isEmailValid) return;
    try {
      await LoadingService.instance.run(() async {
        final result = await _userApi.requestEmailVerifyCode(emailInput.value);
        // if (result is AppSuccess<void>) {
        startResendCountdown();
        Get.to(
            () => SecurityEmailVerificationView(isChangeEmail: isChangeEmail));
        // }
      });
    } catch (_) {}
  }

  void startResendCountdown() {
    _resendTimer?.cancel();
    secondsRemaining.value = resendSeconds;
    _resendTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (secondsRemaining.value <= 1) {
        timer.cancel();
        secondsRemaining.value = 0;
        return;
      }
      secondsRemaining.value -= 1;
    });
  }

  Future<void> submitCode(BuildContext context,
      {bool isChangeEmail = false}) async {
    if (!canSubmitCode) return;
    FocusScope.of(context).unfocus();
    if (isChangeEmail) {
      try {
        await LoadingService.instance.run(() async {
          final result = await _userApi.verifyEmailVerifyCode(
            emailInput.value,
            codeController.text,
          );
          if (result is AppSuccess<void>) {
            AppToast.show(context.l10n.successChanged);
            Get.back();
            Get.back();
            Get.back();
          } else {
            AppToast.show(context.l10n.verifyEmailFailed);
            Get.back();
            Get.back();
            Get.back();
          }
        });
      } catch (_) {}
    } else {
      try {
        await LoadingService.instance.run(() async {
          final result = await _userApi.verifyEmailVerifyCode(
            emailInput.value,
            codeController.text,
          );
          // if (result is AppSuccess<void>) {

          Get.to(() => const SetSecurityEmailPasswordView());

          // }
        });
      } catch (_) {}
    }
  }

  Future<void> setPassword(BuildContext context) async {
    if (!canSetPassword) return;

    try {
      final md5Password =
          md5.convert(utf8.encode(passwordInput.value)).toString();
      await LoadingService.instance.run(() async {
        final result = await _userApi.addSefetyEmail(
          emailInput.value,
          codeController.text,
          md5Password,
        );
        // if (result is AppSuccess<void>) {

        FocusScope.of(context).unfocus();
        AppToast.show(context.l10n.settingsSaved);
        TextInput.finishAutofillContext();
        Get.back();
        Get.back();
        Get.back();

        // }
      });
    } catch (_) {}
  }

  @override
  void onClose() {
    _resendTimer?.cancel();
    emailController.dispose();
    codeController.dispose();
    passwordController.dispose();
    confirmPasswordController.dispose();
    super.onClose();
  }
}