Template
Core 基础设施:Flavor 三包体系、Drift+SQLCipher 加密数据库 7 拦截器 Dio 网络栈、CrashReporter 崩溃日志、Sealed Failure 错误体系 5 色板主题系统、Auth 认证骨架(Clean Architecture)、Dev Panel、Mock Adapter 通过验证:flutter analyze(0 errors)、flutter test(全绿)、staging APK 74.8MB
58 lines
1.5 KiB
Dart
58 lines
1.5 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
/// 短信验证码倒计时 mixin — 抽自 phone_add / old_phone_verify 重复模板。
|
|
///
|
|
/// 用法(任意 [State] 子类,包含 ConsumerState):
|
|
/// ```dart
|
|
/// class _MyPageState extends ConsumerState<MyPage>
|
|
/// with SmsCountdownMixin<MyPage> {
|
|
///
|
|
/// Future<void> _sendCode() async {
|
|
/// await repo.sendSms(phone);
|
|
/// startSmsCountdown(); // 默认 60s
|
|
/// }
|
|
///
|
|
/// @override
|
|
/// Widget build(BuildContext context) {
|
|
/// final text = isSmsCountingDown ? '${smsCountdown}s 后重发' : '发送验证码';
|
|
/// ...
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// dispose 时自动 cancel Timer,子类 `super.dispose()` 即可。
|
|
mixin SmsCountdownMixin<T extends StatefulWidget> on State<T> {
|
|
int _countdown = 0;
|
|
Timer? _timer;
|
|
|
|
/// 当前剩余秒数(0 = 未运行)
|
|
int get smsCountdown => _countdown;
|
|
|
|
/// 是否正在倒计时
|
|
bool get isSmsCountingDown => _countdown > 0;
|
|
|
|
/// 启动倒计时(重复调用会取消上一个 Timer 重新开始)。
|
|
void startSmsCountdown({int seconds = 60}) {
|
|
_timer?.cancel();
|
|
setState(() => _countdown = seconds);
|
|
_timer = Timer.periodic(const Duration(seconds: 1), (t) {
|
|
if (!mounted) {
|
|
t.cancel();
|
|
return;
|
|
}
|
|
setState(() {
|
|
_countdown -= 1;
|
|
if (_countdown <= 0) t.cancel();
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_timer?.cancel();
|
|
super.dispose();
|
|
}
|
|
}
|