import 'dart:async'; import 'dart:developer' as developer; import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../core/network/api_response.dart'; import '../core/network/dio_client.dart'; import '../data/services/auth_service.dart'; // ── State ────────────────────────────────────────────────── class ChangePasswordState { final bool isLoading; final bool isSendingCode; final String? errorMessage; final int codeCooldown; const ChangePasswordState({ this.isLoading = false, this.isSendingCode = false, this.errorMessage, this.codeCooldown = 0, }); ChangePasswordState copyWith({ bool? isLoading, bool? isSendingCode, String? errorMessage, int? codeCooldown, }) => ChangePasswordState( isLoading: isLoading ?? this.isLoading, isSendingCode: isSendingCode ?? this.isSendingCode, errorMessage: errorMessage, codeCooldown: codeCooldown ?? this.codeCooldown, ); } // ── Notifier ─────────────────────────────────────────────── class ChangePasswordNotifier extends Notifier { AuthService get _service => AuthService(ref.read(dioClientProvider)); Timer? _countdownTimer; @override ChangePasswordState build() { ref.onDispose(() => _countdownTimer?.cancel()); return const ChangePasswordState(); } void clearError() => state = state.copyWith(errorMessage: null); /// 发送邮箱验证码 Future sendEmailCode() async { state = state.copyWith(isSendingCode: true, errorMessage: null); try { await _service.sendChangePasswordEmailCode(); state = state.copyWith(isSendingCode: false); _startCountdown(); return true; } catch (e) { state = state.copyWith( isSendingCode: false, errorMessage: _parseError(e), ); return false; } } /// 提交修改登录密码 Future changePassword({ required String oldPassword, required String newPassword, required String vcode, }) async { state = state.copyWith(isLoading: true, errorMessage: null); try { await _service.changeLoginPassword( oldPassword: oldPassword, newPassword: newPassword, vcode: vcode, ); state = state.copyWith(isLoading: false); return true; } catch (e) { state = state.copyWith( isLoading: false, errorMessage: _parseError(e), ); return false; } } void _startCountdown() { _countdownTimer?.cancel(); state = state.copyWith(codeCooldown: 60); _countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) { final remaining = state.codeCooldown - 1; state = state.copyWith(codeCooldown: remaining); if (remaining <= 0) { timer.cancel(); _countdownTimer = null; } }); } String _parseError(Object e) { developer.log('ChangePassword error: $e', name: 'CHANGE_PWD', error: e); if (e is DioException) { if (e.error is ApiException) return (e.error as ApiException).message; final responseData = e.response?.data; if (responseData is Map) { final msg = responseData['message'] as String? ?? responseData['msg'] as String?; if (msg != null && msg.isNotEmpty) return msg; } return e.message ?? 'errNetworkError'; } if (e is ApiException) return e.message; return e.toString(); } } // ── Provider ────────────────────────────────────────────── final changePasswordProvider = NotifierProvider( ChangePasswordNotifier.new, );