248 lines
12 KiB
Dart
Executable File
248 lines
12 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:kaer_with_panels/app/modules/hi_menu/views/hi_menu_view.dart';
|
|
import 'package:kaer_with_panels/app/modules/kr_login/views/kr_login_view.dart';
|
|
import 'package:kaer_with_panels/app/common/app_run_data.dart';
|
|
import 'package:kaer_with_panels/app/widgets/hi_base_scaffold.dart';
|
|
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
|
|
// import 'package:kaer_with_panels/app/widgets/kr_subscription_corner_button.dart';
|
|
import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart';
|
|
import '../../../services/kr_subscribe_service.dart';
|
|
import '../controllers/kr_home_controller.dart';
|
|
import '../models/kr_home_views_status.dart';
|
|
import './hi_animated_connect_button.dart';
|
|
import 'package:kaer_with_panels/app/services/global_overlay_service.dart';
|
|
|
|
import 'package:kaer_with_panels/app/widgets/swipe/has_swipe_config.dart';
|
|
import 'package:kaer_with_panels/app/widgets/swipe/swipe_config.dart';
|
|
import 'package:kaer_with_panels/app/routes/app_pages.dart';
|
|
import 'package:kaer_with_panels/app/utils/account_guard.dart';
|
|
|
|
class KRHomeView extends StatefulWidget implements HasSwipeConfig {
|
|
const KRHomeView({super.key});
|
|
@override
|
|
SwipeConfig get swipeConfig => SwipeConfig(
|
|
enableLeft: true,
|
|
enableRight: true,
|
|
onLeft: () {
|
|
ensureAccountExists().then((ok) {
|
|
if (!ok) return;
|
|
Get.toNamed(Routes.HI_MENU);
|
|
});
|
|
},
|
|
onRight: () {
|
|
ensureAccountExists().then((ok) {
|
|
if (!ok) return;
|
|
GlobalOverlayService.instance.triggerSubscriptionAnimation();
|
|
});
|
|
},
|
|
);
|
|
|
|
@override
|
|
State<KRHomeView> createState() => _KRHomeViewState();
|
|
}
|
|
|
|
class _KRHomeViewState extends State<KRHomeView> {
|
|
late KRHomeController controller;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
controller = Get.find<KRHomeController>();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
// ✅ 在 build 完成后操作 overlay/UI
|
|
if (Get.isRegistered<GlobalOverlayService>()) {
|
|
GlobalOverlayService.instance.updateSubscriptionButtonColor(null);
|
|
}
|
|
});
|
|
return Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
HIBaseScaffold(
|
|
showMenuButton: true,
|
|
topContentAreaHeight: 80,
|
|
child: Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
Align(
|
|
alignment: Alignment.topLeft,
|
|
child: SafeArea(
|
|
child: Padding(
|
|
padding: EdgeInsets.fromLTRB(40.w, 8.w, 0, 0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
'Hi快VPN-网在我在,网快我快',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
// 订阅信息
|
|
Obx(() {
|
|
// 1. 先获取订阅信息
|
|
final currentSubscribe = controller
|
|
.kr_subscribeService.kr_currentSubscribe.value;
|
|
|
|
// 2. 准备一个 Widget 变量,用于存放最终要显示的内容
|
|
Widget content;
|
|
|
|
// --- 定义统一的文本样式,并设置行高 ---
|
|
final normalStyle = TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
height: 1.2,
|
|
);
|
|
final highlightStyle = normalStyle.copyWith(
|
|
color: const Color(0xFFFF00B7),
|
|
);
|
|
|
|
// 3. 开始条件判断
|
|
if (currentSubscribe == null) {
|
|
// --- 情况1: 没有任何订阅信息 ---
|
|
content = Text(
|
|
'尚未购买套餐',
|
|
style: highlightStyle,
|
|
);
|
|
} else {
|
|
// --- 情况2: 有订阅信息,需要判断是否过期 ---
|
|
final now = DateTime.now();
|
|
DateTime? expireDateTime;
|
|
try {
|
|
expireDateTime =
|
|
DateTime.parse(currentSubscribe.expireTime);
|
|
} catch (e) {
|
|
// 日期格式解析失败
|
|
}
|
|
|
|
if (expireDateTime != null &&
|
|
expireDateTime.isBefore(now)) {
|
|
// --- 情况2.1: 订阅已过期 ---
|
|
final formattedExpireDate =
|
|
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
|
// 使用换行符 \n 合并为单个 Text 组件
|
|
content = Text(
|
|
'您的套餐已于 $formattedExpireDate 到期\n请前往购买新套餐',
|
|
style: highlightStyle,
|
|
);
|
|
} else {
|
|
// --- 情况2.2: 订阅有效 ---
|
|
final formattedExpireTime = expireDateTime != null
|
|
? '${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')} ${expireDateTime.hour.toString().padLeft(2, '0')}:${expireDateTime.minute.toString().padLeft(2, '0')}'
|
|
: '未知';
|
|
// 使用换行符 \n 合并为单个 Text 组件
|
|
content = Text(
|
|
'套餐到期时间:$formattedExpireTime\n${controller.kr_isConnected.value ? '当前线路:${controller.kr_getRealConnectedNodeCountry()}' : '未连接'}',
|
|
style: normalStyle,
|
|
);
|
|
}
|
|
}
|
|
|
|
// 4. 返回包裹在公共 Container 中的最终内容
|
|
return Container(
|
|
alignment: Alignment.centerLeft,
|
|
padding: EdgeInsets.only(top: 8.h),
|
|
child: content,
|
|
);
|
|
}),
|
|
SizedBox(height: 8.h), // 添加一些垂直间距
|
|
|
|
// --- 自定义“闪连”Checkbox ---
|
|
Obx(() {
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min, // 让 Row 的宽度包裹其内容
|
|
children: [
|
|
// --- 可点击的 Checkbox 区域 ---
|
|
GestureDetector(
|
|
// 点击方框和文字都可以切换状态
|
|
onTap: () => controller.toggleQuickConnect(
|
|
!controller.isQuickConnectEnabled.value),
|
|
child: AbsorbPointer(
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// 1. 自定义 Checkbox 的方框外观
|
|
Container(
|
|
width: 20,
|
|
height: 20,
|
|
decoration: BoxDecoration(
|
|
color: controller
|
|
.isQuickConnectEnabled.value
|
|
? Theme.of(context).primaryColor
|
|
: Colors.transparent,
|
|
border: Border.all(
|
|
color:
|
|
Theme.of(context).primaryColor,
|
|
width: 1.5,
|
|
),
|
|
borderRadius:
|
|
BorderRadius.circular(4.r),
|
|
),
|
|
child: controller
|
|
.isQuickConnectEnabled.value
|
|
? Icon(
|
|
Icons.check,
|
|
size: 14,
|
|
color: Colors.black,
|
|
)
|
|
: null,
|
|
),
|
|
SizedBox(width: 8),
|
|
// 2. “闪连”标签
|
|
Text(
|
|
'闪连',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
// --- 问号图标和点击弹窗区域 ---
|
|
SizedBox(width: 6), // 文字和问号图标之间的间距
|
|
GestureDetector(
|
|
onTap: () {
|
|
HIDialog.show(
|
|
title: '闪连功能',
|
|
message:
|
|
'开启后,每次打开软件默认自动连接,无需点击连接按钮\n在后台关闭软件后,软件将自动断开',
|
|
);
|
|
},
|
|
child: KrLocalImage(
|
|
imageName: 'question-icon', // 图片名称
|
|
imageType: ImageType.svg, // 图片类型
|
|
width: 24,
|
|
height: 24,
|
|
color: Colors.white, // 让图标颜色与边框协调
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// 将 HIAnimatedConnectButton 移到 HIBaseScaffold 外部,避免 SafeArea 约束
|
|
HIAnimatedConnectButton(),
|
|
],
|
|
);
|
|
}
|
|
}
|