|
@@ -1,4 +1,6 @@
|
|
|
import 'dart:async';
|
|
import 'dart:async';
|
|
|
|
|
+import 'package:flutter/foundation.dart';
|
|
|
|
|
+
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
@@ -6,6 +8,7 @@ import 'package:location/utils/common_expand.dart';
|
|
|
|
|
|
|
|
import '../../data/bean/member_status_info.dart';
|
|
import '../../data/bean/member_status_info.dart';
|
|
|
import '../../resource/string.gen.dart';
|
|
import '../../resource/string.gen.dart';
|
|
|
|
|
+import 'mine_countdown_timer_manager.dart'; // 导入全局定时器管理器
|
|
|
|
|
|
|
|
class MineTrialMembershipCountdownText extends StatefulWidget {
|
|
class MineTrialMembershipCountdownText extends StatefulWidget {
|
|
|
final MemberStatusInfo? memberStatusInfo;
|
|
final MemberStatusInfo? memberStatusInfo;
|
|
@@ -14,7 +17,7 @@ class MineTrialMembershipCountdownText extends StatefulWidget {
|
|
|
const MineTrialMembershipCountdownText({
|
|
const MineTrialMembershipCountdownText({
|
|
|
super.key,
|
|
super.key,
|
|
|
this.memberStatusInfo,
|
|
this.memberStatusInfo,
|
|
|
- this.trialHasExpiredCallBack
|
|
|
|
|
|
|
+ this.trialHasExpiredCallBack,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
@override
|
|
@@ -22,14 +25,15 @@ class MineTrialMembershipCountdownText extends StatefulWidget {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
class _MineTrialMembershipCountdownTextState extends State<MineTrialMembershipCountdownText> {
|
|
class _MineTrialMembershipCountdownTextState extends State<MineTrialMembershipCountdownText> {
|
|
|
- Timer? _timer; // 使用可空类型,初始化为null
|
|
|
|
|
|
|
+ final MineCountdownTimerManager _timerManager = MineCountdownTimerManager();
|
|
|
String _countdownText = '';
|
|
String _countdownText = '';
|
|
|
- bool _isCountdownActive = false; // 标记倒计时是否活跃
|
|
|
|
|
|
|
+ late String _countdownKey; // 倒计时唯一标识
|
|
|
|
|
|
|
|
@override
|
|
@override
|
|
|
void initState() {
|
|
void initState() {
|
|
|
super.initState();
|
|
super.initState();
|
|
|
- _initParameter();
|
|
|
|
|
|
|
+ _countdownKey = 'member_trial_countdown_${widget.memberStatusInfo?.hashCode ?? ''}';
|
|
|
|
|
+ _initCountdown();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
@override
|
|
@@ -37,131 +41,96 @@ class _MineTrialMembershipCountdownTextState extends State<MineTrialMembershipCo
|
|
|
super.didUpdateWidget(oldWidget);
|
|
super.didUpdateWidget(oldWidget);
|
|
|
// 检查memberStatusInfo是否有变化
|
|
// 检查memberStatusInfo是否有变化
|
|
|
if (widget.memberStatusInfo != oldWidget.memberStatusInfo) {
|
|
if (widget.memberStatusInfo != oldWidget.memberStatusInfo) {
|
|
|
-
|
|
|
|
|
- DateTime endTime = DateTime.fromMillisecondsSinceEpoch(widget.memberStatusInfo!.trialEndTimestamp ?? 0);
|
|
|
|
|
- Duration remaining = endTime.difference(DateTime.now());
|
|
|
|
|
- if (!_isCountdownActive) {
|
|
|
|
|
- _resetTimer();
|
|
|
|
|
- _initParameter();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _countdownKey = 'member_trial_countdown_${widget.memberStatusInfo?.hashCode ?? ''}';
|
|
|
|
|
+ _initCountdown();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void _initParameter() {
|
|
|
|
|
- // 清除现有计时器
|
|
|
|
|
- _resetTimer();
|
|
|
|
|
-
|
|
|
|
|
- // 创建倒计时定时器
|
|
|
|
|
- if (widget.memberStatusInfo?.trialed == true) {
|
|
|
|
|
- // 计算剩余时间
|
|
|
|
|
- DateTime endTime = DateTime.fromMillisecondsSinceEpoch(widget.memberStatusInfo!.trialEndTimestamp ?? 0);
|
|
|
|
|
- Duration remaining = endTime.difference(DateTime.now());
|
|
|
|
|
- if (remaining.inSeconds > 0) {
|
|
|
|
|
- print("创建新的倒计时定时器");
|
|
|
|
|
- // 创建每秒更新一次的定时器
|
|
|
|
|
- _timer = Timer.periodic(const Duration(seconds: 1), (_) => _countdownisInProgress());
|
|
|
|
|
- _isCountdownActive = true;
|
|
|
|
|
- _updateTime();
|
|
|
|
|
- _countdownisInProgress();
|
|
|
|
|
- } else {
|
|
|
|
|
- _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- // 将时间戳转换为DateTime(根据单位处理)
|
|
|
|
|
|
|
+ void _initCountdown() {
|
|
|
|
|
+ if (widget.memberStatusInfo == null) {
|
|
|
_countdownText = StringName.memberExperienceVip;
|
|
_countdownText = StringName.memberExperienceVip;
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- void _resetTimer() {
|
|
|
|
|
- // 取消现有计时器并重置状态
|
|
|
|
|
- _timer?.cancel();
|
|
|
|
|
- _timer = null;
|
|
|
|
|
- _isCountdownActive = false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (widget.memberStatusInfo?.trialed != true) {
|
|
|
|
|
+ _countdownText = StringName.memberExperienceVip;
|
|
|
|
|
+ _timerManager.cancelCountdown(_countdownKey);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- void _updateTime() {
|
|
|
|
|
- // 将时间戳转换为DateTime(根据单位处理)
|
|
|
|
|
- _countdownText = StringName.memberExperienceVip;
|
|
|
|
|
-
|
|
|
|
|
- if ((widget.memberStatusInfo?.trialed ?? false)) {
|
|
|
|
|
- DateTime endTime = DateTime.fromMillisecondsSinceEpoch(widget.memberStatusInfo!.trialEndTimestamp ?? 0);
|
|
|
|
|
- Duration remaining = endTime.difference(DateTime.now());
|
|
|
|
|
- ///正在使用
|
|
|
|
|
- if (remaining.inSeconds > 0) {
|
|
|
|
|
- if (!_isCountdownActive) {
|
|
|
|
|
- _countdownisInProgress();
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- //已经使用完了
|
|
|
|
|
- _resetTimer();
|
|
|
|
|
- _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- // 未试用或其他状态
|
|
|
|
|
- _resetTimer();
|
|
|
|
|
|
|
+ final timestamp = widget.memberStatusInfo!.trialEndTimestamp ?? 0;
|
|
|
|
|
+ if (timestamp == 0) {
|
|
|
|
|
+ _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
+ _timerManager.cancelCountdown(_countdownKey);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- setState(() {});
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- /// 正在倒计时
|
|
|
|
|
- void _countdownisInProgress() {
|
|
|
|
|
- // 检查时间戳是否为空
|
|
|
|
|
- _countdownText = StringName.memberExperienceVip;
|
|
|
|
|
- // 将时间戳转换为DateTime(根据单位处理)
|
|
|
|
|
- final timestamp = widget.memberStatusInfo!.trialEndTimestamp!;
|
|
|
|
|
- DateTime endTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
|
|
|
|
- Duration remaining = endTime.difference(DateTime.now());
|
|
|
|
|
- //print("倒计时状态---${widget.memberStatusInfo!.trialEndTimestamp}---:${remaining.inSeconds}---${remaining.inSeconds <= 0}---:${DateTime.now()}---:${endTime}");
|
|
|
|
|
-
|
|
|
|
|
- if (widget.memberStatusInfo?.trialed == true) {
|
|
|
|
|
- if (remaining.inSeconds == 0) {
|
|
|
|
|
- _resetTimer(); // 取消计时器并重置状态
|
|
|
|
|
- _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
- setState(() {});
|
|
|
|
|
- if (widget.trialHasExpiredCallBack != null) {
|
|
|
|
|
- widget.trialHasExpiredCallBack!();
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- //已经使用完了
|
|
|
|
|
- _countdownText = _formatDuration(remaining);
|
|
|
|
|
- _countdownText = '${StringName.memberCountdownRemaining} ${_countdownText} ${StringName.memberCountdownExperienceTime}';
|
|
|
|
|
- if (mounted) {
|
|
|
|
|
- setState(() {});
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 启动全局倒计时
|
|
|
|
|
+ _timerManager.startCountdown(
|
|
|
|
|
+ key: _countdownKey,
|
|
|
|
|
+ endTimestamp: timestamp,
|
|
|
|
|
+ onExpired: () {
|
|
|
|
|
+ if (mounted) {
|
|
|
|
|
+ setState(() {
|
|
|
|
|
+ _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
- } else {
|
|
|
|
|
- _resetTimer();
|
|
|
|
|
- _countdownText = StringName.memberExperienceVip;
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ //widget.trialHasExpiredCallBack?.call();
|
|
|
|
|
+
|
|
|
|
|
+ // 订阅倒计时更新
|
|
|
|
|
+ _timerManager.getCountdownStream(_countdownKey).listen((formattedTime) {
|
|
|
if (mounted) {
|
|
if (mounted) {
|
|
|
- setState(() {});
|
|
|
|
|
|
|
+ setState(() {
|
|
|
|
|
+ _countdownText = '${StringName.memberCountdownRemaining} $formattedTime ${StringName.memberCountdownExperienceTime}';
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
|
|
+ // 初始化时计算一次剩余时间
|
|
|
|
|
+ _updateInitialTime();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- String _formatDuration(Duration duration) {
|
|
|
|
|
- String twoDigits(int n) => n.toString().padLeft(2, '0');
|
|
|
|
|
- String hours = twoDigits(duration.inHours);
|
|
|
|
|
- String minutes = twoDigits(duration.inMinutes.remainder(60));
|
|
|
|
|
- String seconds = twoDigits(duration.inSeconds.remainder(60));
|
|
|
|
|
- return '$hours:$minutes:$seconds';
|
|
|
|
|
|
|
+ void _updateInitialTime() {
|
|
|
|
|
+ if (widget.memberStatusInfo == null || widget.memberStatusInfo?.trialed != true) {
|
|
|
|
|
+ _countdownText = StringName.memberExperienceVip;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ final timestamp = widget.memberStatusInfo!.trialEndTimestamp ?? 0;
|
|
|
|
|
+ if (timestamp == 0) {
|
|
|
|
|
+ _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ DateTime endTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
|
|
|
|
+ Duration remaining = endTime.difference(DateTime.now());
|
|
|
|
|
+
|
|
|
|
|
+ if (remaining.inSeconds > 0) {
|
|
|
|
|
+ String formattedTime = _timerManager.formatDuration(remaining);
|
|
|
|
|
+ _countdownText = '${StringName.memberCountdownRemaining} $formattedTime ${StringName.memberCountdownExperienceTime}';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ _countdownText = StringName.memberTrialHasExpired;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
@override
|
|
|
void dispose() {
|
|
void dispose() {
|
|
|
- _resetTimer(); // 使用统一的方法清理计时器
|
|
|
|
|
|
|
+ //_timerManager.cancelCountdown(_countdownKey);
|
|
|
super.dispose();
|
|
super.dispose();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
Widget build(BuildContext context) {
|
|
|
- return Text(
|
|
|
|
|
- _countdownText,
|
|
|
|
|
- style: TextStyle(
|
|
|
|
|
- fontSize: 13.sp,
|
|
|
|
|
- color: "#8A5F03".color,
|
|
|
|
|
- fontWeight: FontWeight.bold
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ return Text(
|
|
|
|
|
+ _countdownText,
|
|
|
|
|
+ style: TextStyle(
|
|
|
|
|
+ fontSize: 13.sp,
|
|
|
|
|
+ color: "#8A5F03".color,
|
|
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
|
|
+ ),
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+}
|