import 'dart:async'; import 'dart:convert' as convert; import 'package:fast/constants.dart'; import 'package:fast/model/model.dart'; import 'package:fast/utils/api.dart'; import 'package:fast/utils/global.dart'; import 'package:fast/utils/http_utils.dart'; import 'package:fast/utils/size_fit.dart'; import 'package:fast/view/component/challenge_checkin.dart'; import 'package:fast/view/component/change_time.dart'; import 'package:fast/view/component/header.dart'; import 'package:fast/view/component/share.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'component/challenge_checkout.dart'; import 'component/eat.dart'; import 'component/loading.dart'; import 'component/fast.dart'; import 'package:intl/intl.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State createState() => HomeScreenState(); } GlobalKey eatKey = GlobalKey(); GlobalKey fastKey = GlobalKey(); class HomeScreenState extends State with SingleTickerProviderStateMixin, WidgetsBindingObserver { late AnimationController controller; late Animation animation0; late Animation animation1; double topOffset = -40; double bottomOffset = 0; double bottom = 0; bool showEating = false; bool showFasting = false; bool showLoading = true; bool hasPopPage = false; Map? onlineObj; Timer? timerUpdate; String? strSysTime; List list = []; @override void initState() { super.initState(); var zone = DateTime.now().timeZoneOffset; WidgetsBinding.instance?.addObserver(this); Global().fastKey = fastKey; Global().homePage = this; loadCache(); getConfig(); getDatas(); // getSystemTime(); // getFastStatus(); // getBalance(); // getOnlineUser(); controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 2000)); controller.addListener(() { setState(() {}); }); animation0 = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: controller, curve: const Interval(0.05, 0.2))); animation1 = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: controller, curve: const Interval(0.825, 1))); Timer(const Duration(milliseconds: 200), () { controller.forward(); setState(() { topOffset = 0; bottomOffset = bottom; }); }); Timer(const Duration(seconds: 1), () { if (Global().userBean != null) { showShare(); } }); } @override void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: getDatas(); break; case AppLifecycleState.inactive: break; case AppLifecycleState.paused: break; case AppLifecycleState.detached: break; } } Future loadCache() async { final prefs = await SharedPreferences.getInstance(); String? temp = prefs.getString('userInfo'); if (temp != null) { Map data = convert.jsonDecode(temp); UserBean bean = UserBean.fromJson(data); Global().userBean = bean; } } void getDatas() async { List list = await Future.wait([ getSystemTime(), getFastStatus(), getBalance(), getOnlineUser(), getUserInfo() ]); if (list[1] != null) { FastBean fastBean = list[1]; if (fastBean.ongoing == false) { Global().currentFast = null; showFastContent(); return; } Global().currentFast = fastBean; if (fastBean.needConfirm) { showCheckout(true); return; } int t = DateTime.now().millisecondsSinceEpoch ~/ 1000 + Global().timeSeconds; if (fastBean.mode == 'CHALLENGER' && fastBean.status == 'DOING') { int index = fastBean.currentDayIndex! - 1; if (t >= fastBean.startTime! && fastBean.checkinDays![index].checkinTime == null) { bool supertimeout = t - fastBean.startTime! >= 3600 * 24; showCheckin(false); if (supertimeout) { return; } } if (t + 1 < fastBean.startTime!) { setState(() { showEating = true; showFasting = false; showLoading = false; }); return; } } showFastContent(); } } @override void dispose() { controller.dispose(); super.dispose(); } checkUpdate() { setState(() { showEating = false; showFasting = false; showLoading = true; }); Timer(const Duration(seconds: 2), () { getDatas(); }); } Future getConfig() async { Map data = await HttpUtils.get(Api.serverConfig); Global().thirdLogin = data['thirdparty_login']; Global().pushEnable = false; //data['push_enable']; Global().payEnable = data['pay_enable']; } Future getSystemTime() async { Map data = await HttpUtils.get(Api.serverTime); TimeBean timeBean = TimeBean.fromJson(data); // respo. var now = DateTime.now().millisecondsSinceEpoch ~/ 1000; Global().timeSeconds = timeBean.server_ts! - now; showSystemTime(); return timeBean; // var ts = respone.server_ts; } Future showCheckin(bool abandon) async { if (hasPopPage) { return; } hasPopPage = true; int timestamp = serverTime().millisecondsSinceEpoch ~/ 1000; Map data = await HttpUtils.get(Api.check, params: {"time": timestamp}); showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, useSafeArea: false, builder: (BuildContext context) { return FastCheckin( abandon: abandon, supertimeout: data['checkin_status'] == 'TIMEOUT_EXIT', fast: Global().currentFast!, timestamp: timestamp, checkInfo: data, ); }); } Future showCheckout(bool abandon) async { if (hasPopPage) { return; } hasPopPage = true; int timestamp = serverTime().millisecondsSinceEpoch ~/ 1000; Map data = await HttpUtils.get(Api.check, params: {"time": timestamp}); showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, useSafeArea: false, builder: (BuildContext context) { return FastCheckout( abandon: abandon, supertimeout: data['checkout_status'] == 'TIMEOUT_EXIT', fast: Global().currentFast!, timestamp: timestamp, checkInfo: data, ); }); } void closeCheckPop() { hasPopPage = false; getDatas(); } void showSystemTime() { if (timerUpdate != null) { timerUpdate!.cancel(); } timerUpdate = Timer.periodic(const Duration(seconds: 1), (e) { int milliseconds = DateTime.now().millisecondsSinceEpoch; milliseconds = milliseconds + Global().timeSeconds * 1000; DateTime dt = DateTime.fromMillisecondsSinceEpoch(milliseconds); if (mounted) { setState(() { strSysTime = DateFormat('yyyy-MM-dd HH:mm:ss').format(dt); }); } }); } Future getFastStatus() async { Map data = await HttpUtils.get(Api.current); FastBean fastBean = FastBean.fromJson(data); setState(() { if (fastBean.ongoing!) { list = data['notify_points']; } else { list = []; } }); return fastBean; // var ts = respone.server_ts; } Future getBalance() async { Map data = await HttpUtils.get(Api.balance); Global().balance = data['rjv_balance']; return data; } Future getOnlineUser() async { Map data = await HttpUtils.get(Api.onlineUsers); setState(() { onlineObj = data; }); return data; // Global().balance = data['rjv_balance']; } Future getUserInfo() async { Map data = await HttpUtils.get(Api.userInfo); UserBean bean = UserBean.fromJson(data); Global().userBean = bean; final prefs = await SharedPreferences.getInstance(); await prefs.setString('userInfo', convert.jsonEncode(data)); String? temp = prefs.getString('userInfo'); Map bb = convert.jsonDecode(temp!); print(bb.toString()); return data; } void eatEnd() { setState(() { showEating = false; showFasting = false; showLoading = true; }); showCheckin(false); Timer(const Duration(seconds: 3), () { getDatas(); }); } void showLogin() {} showFastContent() { setState(() { showEating = false; showFasting = true; showLoading = false; }); Timer(const Duration(milliseconds: 200), () { if (fastKey.currentContext != null) { FastState seekBar = fastKey.currentState as FastState; seekBar.updateProgress(); } }); } @override Widget build(BuildContext context) { SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); // final Controller c = Get.put(Controller()); SizeFit.initialize(context); var size = MediaQuery.of(context).size; EdgeInsets safePadding = MediaQuery.of(context).padding; bottom = safePadding.bottom; return Scaffold( body: Stack( children: [ AnimatedPositioned( duration: const Duration(milliseconds: 300), top: topOffset, child: Opacity( opacity: animation0.value, child: Header(isIndexPage: true), )), Container( margin: EdgeInsets.only(top: 180.px, bottom: bottom), // alignment: Alignment.center, color: kBgColor, child: Stack(children: [ Column( mainAxisSize: MainAxisSize.max, children: [ if (showFasting) Expanded( child: ClipRect( clipBehavior: Clip.hardEdge, child: Container( alignment: Alignment.topCenter, margin: EdgeInsets.only( bottom: 20.px, top: size.height > 667.px ? 30.px : 10.px), color: kBgColor, child: Transform.scale( alignment: Alignment.topCenter, scale: Global().scale, child: Fast( key: fastKey, )), ), )), if (showEating) Expanded( child: Container( alignment: Alignment.topCenter, margin: EdgeInsets.only(bottom: 20.px), color: kBgColor, child: Transform.scale( alignment: Alignment.topCenter, scale: Global().scale, child: Eat( key: eatKey, )))), if (showLoading) Expanded( child: Container( alignment: Alignment.topCenter, margin: EdgeInsets.only(top: 50.px), color: kBgColor, child: Loading())), ], ), Positioned( left: 0, right: 0, bottom: 60.px, child: Column( children: [ if (onlineObj != null) Opacity( opacity: animation1.value, child: Stack( alignment: AlignmentDirectional.topStart, children: [ bottomAvatar(4, const Color(0xCC080C1A)), bottomAvatar(3, const Color(0x99080C1A)), bottomAvatar(2, const Color(0x66080C1A)), bottomAvatar(1, const Color(0x33080C1A)), bottomAvatar(0, const Color(0x00080C1A)), Container( margin: EdgeInsets.fromLTRB( 12 * 4.px + 24.px + 8.px, 1.px, 0, 0), height: 22.px, child: Text( '当前' + onlineObj!['user_count'].toString() + '人在线', style: TextStyle( color: const Color(0x66FFFFFF), fontSize: 14.px, height: 1.4), ), ) ], ), ), SizedBox( height: 24.px, ) ], )) ])), Positioned( left: 20.px, top: 200.px, child: GestureDetector( onTap: () { showTimelist(); //调表界面 }, child: Container( width: 60.px, height: 36.px, alignment: Alignment.center, decoration: BoxDecoration( color: const Color(0x1AC4CCDA), borderRadius: BorderRadius.all(Radius.circular(12.px))), child: Text( '调表', style: TextStyle( color: Colors.white, fontSize: 14.px, fontWeight: FontWeight.bold), ), ), )) /*Positioned( left: 0, top: 50, right: 0, height: list.isEmpty ? 30.px : list.length == 1 ? 100.px : 200.px, child: Opacity( opacity: 1.0, child: Container( color: const Color(0xddf5deb3), padding: const EdgeInsets.only(left: 20, right: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Row( children: [ GestureDetector( child: const Text('请选择'), onTap: () { showPicker(); }, ), SizedBox( width: 20.px, ), GestureDetector( onTap: () { updateTimes(0); }, child: const Text('重置'), ), if (strSysTime != null) Expanded( child: Text( '系统时间:${strSysTime!}', textAlign: TextAlign.right, style: TextStyle(fontSize: 8.px), )) ], ), Expanded( child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ ...List.generate(list.length, (i) { return Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ ...List.generate( list[i]['contents'].length, (index) { String strColor = list[i]['contents'] [index]['fColor']; strColor = strColor.substring(2, 10); int value = int.parse(strColor, radix: 16); return Text( list[i]['contents'][index]['content'], textAlign: TextAlign.right, style: TextStyle( fontSize: 8.px, color: Color(value)), ); }), Text( '--------------------------------------', style: TextStyle( color: Colors.black, fontSize: 8.px), ) ], ); }) ], ), )) ], )))),*/ ], ), ); } showTimelist() { showDialog( context: context, barrierDismissible: false, useSafeArea: false, barrierColor: Colors.transparent, builder: (BuildContext context) { return ChangeTime(list: list,callback: (){ getDatas(); },); }); } DateTime serverTime() { int milliseconds = DateTime.now().millisecondsSinceEpoch; milliseconds = milliseconds + Global().timeSeconds * 1000; return DateTime.fromMillisecondsSinceEpoch(milliseconds); } showPicker() { DatePicker.showDatePicker(context, showTitleActions: true, currentTime: serverTime(), theme: const DatePickerTheme( headerColor: Colors.orange, backgroundColor: Colors.white, itemStyle: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 18), doneStyle: TextStyle(color: Colors.white, fontSize: 16)), onConfirm: (date) { DatePicker.showTimePicker(context, showTitleActions: true, currentTime: serverTime(), theme: const DatePickerTheme( headerColor: Colors.orange, backgroundColor: Colors.white, itemStyle: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 18), doneStyle: TextStyle(color: Colors.white, fontSize: 16)), onConfirm: (date2) { DateTime dt = DateTime.parse(date.year.toString() + '-' + (date.month.toString()).padLeft(2, '0') + '-' + (date.day.toString()).padLeft(2, '0') + 'T' + (date2.hour.toString()).padLeft(2, '0') + ':' + (date2.minute.toString()).padLeft(2, '0') + ':' + (date2.second.toString()).padLeft(2, '0')); int seconds = (dt.millisecondsSinceEpoch - DateTime.now().millisecondsSinceEpoch) ~/ 1000; updateTimes(seconds); }); // int seconds = (date.millisecondsSinceEpoch - // DateTime.now().millisecondsSinceEpoch) ~/ // 1000; // updateTimes(seconds); }); // DatePicker.showDateTimePicker(context, // showTitleActions: true, // currentTime: serverTime(), // theme: const DatePickerTheme( // headerColor: Colors.orange, // backgroundColor: Colors.white, // itemStyle: TextStyle( // color: Colors.black, fontWeight: FontWeight.bold, fontSize: 18), // doneStyle: TextStyle(color: Colors.white, fontSize: 16)), // onConfirm: (date) { // int seconds = (date.millisecondsSinceEpoch - // DateTime.now().millisecondsSinceEpoch) ~/ // 1000; // updateTimes(seconds); // }); } Future updateTimes(seconds) async { Map data = await HttpUtils.get(Api.fixTime, params: {"fix": seconds}); getDatas(); } showShare() { // showDialog( // context: context, // barrierDismissible: false, // barrierColor: const Color(0xF2000D1F), // builder: (BuildContext context) { // return const Share(); // }); } bottomAvatar(int index, Color color) { if (onlineObj!['recent_users'].length > index) { return Container( width: 24.px, height: 24.px, margin: EdgeInsets.fromLTRB(index * 12.px, 0, 0, 0), child: Stack( children: [ ClipOval( child: Image.network( onlineObj!['recent_users'][index]['avatar'], width: 24.px, height: 24.px, fit: BoxFit.cover, ), ), Container( width: 24.px, height: 24.px, decoration: BoxDecoration( color: color, shape: BoxShape.circle, border: Border.all(color: const Color(0xFF000D26))), ) ], ), ); } return SizedBox( width: 0.px, height: 0.px, ); } }