| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- import 'dart:async';
- import 'package:fast/extension/button.dart';
- import 'package:fast/extension/relation.dart';
- import 'package:fast/model/model.dart';
- import 'package:fast/utils/global.dart';
- import 'package:fast/utils/size_fit.dart';
- import 'package:fast/utils/util.dart';
- import 'package:flutter/material.dart';
- import 'alert_widget.dart';
- import 'bubble_widget.dart';
- import 'challenge_checkout.dart';
- class Eat extends StatefulWidget {
- const Eat({Key? key}) : super(key: key);
- @override
- _EatState createState() => _EatState();
- }
- class _EatState extends State<Eat> {
- final GlobalKey globalKey = GlobalKey();
- FastBean currentFast = Global().currentFast!;
- late Timer timer;
- double x = 38.px;
- int s = 6;
- @override
- void initState() {
- super.initState();
- WidgetsBinding.instance?.addPostFrameCallback((_) {
- setState(() {
- var obj = globalKey.currentContext;
- var width = obj?.size!.width;
- x = (width! / 2 + 17.px) * 2;
- });
- });
- timer = Timer.periodic(const Duration(seconds: 1), (e) {
- setState(() {
- s--;
- if (s == 0) {
- timer.cancel();
- }
- });
- });
- }
- @override
- void didChangeDependencies() {
- super.didChangeDependencies();
- }
- @override
- void dispose() {
- timer.cancel();
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- int fastTime = (currentFast.endTime! - currentFast.startTime!) ~/ 60;
- int fastHour = fastTime ~/ 60;
- int fastMinute = fastTime % 60.toInt();
- int eatMinute = fastMinute == 0 ? 0 : 60 - fastMinute;
- int eatHour = fastMinute == 0 ? 24 - fastHour : 23 - fastHour;
- String strFast = '';
- String strEat = '';
- if (fastMinute == 0) {
- strFast = fastHour.toString();
- strEat = eatHour.toString();
- } else {
- strFast =
- fastHour.toString() + ':' + fastMinute.toString().padLeft(2, '0');
- strEat = eatHour.toString() + ':' + eatMinute.toString().padLeft(2, '0');
- }
- Size sz = Util().boundingTextSize(
- strEat, TextStyle(fontFamily: 'Exo2', fontSize: 32.px));
- return Stack(children: [
- Positioned(top: 10.px, right: 0.px, child: const Progress()),
- Column(mainAxisAlignment: MainAxisAlignment.start, children: [
- SizedBox(
- height: 30.px,
- ),
- const Bubble(),
- SizedBox(
- height: 30.px,
- ),
- if (s > 0)
- Row(mainAxisAlignment: MainAxisAlignment.center, children: [
- Expanded(
- child: Text(
- strFast,
- textAlign: TextAlign.right,
- style: TextStyle(
- color: const Color(0x99FFFFFF),
- fontFamily: 'Exo2',
- fontSize: 32.px),
- ),
- ),
- SizedBox(
- width: 12.px,
- ),
- Text('/',
- style: TextStyle(
- color: const Color(0x99FFFFFF),
- fontFamily: 'Exo2',
- fontSize: 16.px)),
- SizedBox(
- width: 12.px,
- ),
- Expanded(
- child: Row(
- children: [
- if (s > 2)
- Text(
- strEat,
- key: globalKey,
- style: TextStyle(
- color: const Color(0xFFFF9B00),
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600,
- fontSize: 32.px),
- ).relationOne(
- -49.px + sz.width / 2.0,
- -40,
- BubbleWidget(
- 94.px,
- 42.px,
- const Color(0xFFFF9B00),
- BubbleArrowDirection.bottom,
- arrAngle: 80.px,
- arrHeight: 8.px,
- child: Text(
- '进食开始…',
- style: TextStyle(
- color: Colors.black,
- fontSize: 14.px,
- fontWeight: FontWeight.bold),
- ),
- )),
- if (s <= 2)
- Container(
- margin: EdgeInsets.only(bottom: 4.px),
- child: Text(
- strEat,
- key: globalKey,
- style: TextStyle(
- color: const Color(0xFFFF9B00),
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600,
- fontSize: 32.px),
- ),)
- ],
- ))
- ]),
- if (s <= 0)
- Container(
- alignment: Alignment.center,
- child: RRectButton(
- '结束挑战',
- width: 144.px,
- height: 50.px,
- backgroundColor: const Color(0x1AC4CCDA),
- textColor: const Color(0xFFC4CCDA),
- radius: 25.px,
- fontSize: 16.px,
- onPressed: () => end(),
- ),
- )
- ])
- ]);
- }
- end() {
- if (Global().allowNotification == false && Global().pushEnable) {
- Util().showNotificationStatus(context);
- return;
- }
- showConfirm('确定现在退出\n"${currentFast.days}天连续计划"吗?', () {
- Global().homePage.showCheckout(true);
- });
- }
- void showConfirm(String title, Function() confirmCallback) {
- showDialog(
- context: context,
- barrierDismissible: false,
- barrierColor: const Color(0xF2000D1F),
- builder: (BuildContext context) {
- return AlertWidget(
- title: title,
- confirm: '确定',
- confirmCallback: () {
- Navigator.of(context).pop();
- confirmCallback();
- });
- });
- }
- }
- class Progress extends StatefulWidget {
- const Progress({Key? key}) : super(key: key);
- @override
- _ProgressState createState() => _ProgressState();
- }
- class _ProgressState extends State<Progress> {
- late FastBean fastBean;
- @override
- void initState() {
- fastBean = Global().currentFast!;
- super.initState();
- }
- @override
- Widget build(BuildContext context) {
- return Container(
- width: 64.px,
- height: 54.px,
- alignment: Alignment.center,
- margin: EdgeInsets.fromLTRB(0, 0, 14.px, 0.px),
- decoration: BoxDecoration(
- color: const Color(0x1AFFFFFF),
- borderRadius: BorderRadius.all(Radius.circular(12.px))),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- SizedBox(height: 5.px,),
- Container(
- padding: EdgeInsets.fromLTRB(0, 0, 0, 6.px),
- decoration: BoxDecoration(
- border: Border(
- bottom: BorderSide(
- color: const Color(0x1AFFFFFF), width: 1.px))),
- child: Text(
- '${fastBean.days}天挑战',
- style:
- TextStyle(color: const Color(0x66FFFFFF), fontSize: 10.px),
- ),
- ),
- SizedBox(
- height: 2.px,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Text(
- '${fastBean.finishDays}',
- style: TextStyle(
- color: const Color(0xFFC4CCDA),
- fontSize: 16.px,
- fontWeight: FontWeight.bold,
- fontFamily: 'Exo2'),
- ),
- const SizedBox(
- width: 3,
- ),
- Text(
- '/',
- style:
- TextStyle(color: const Color(0xFFC4CCDA), fontSize: 9.px),
- ),
- const SizedBox(
- width: 3,
- ),
- Text(
- '${fastBean.days}',
- style: TextStyle(
- color: const Color(0xFFC4CCDA),
- fontSize: 16.px,
- fontWeight: FontWeight.bold,
- fontFamily: 'Exo2'),
- )
- ],
- )
- ],
- ));
- }
- }
- class Bubble extends StatelessWidget {
- const Bubble({Key? key}) : super(key: key);
- @override
- Widget build(BuildContext context) {
- return Stack(children: [
- BubbleRotation(
- key: UniqueKey(),
- duration: 3000,
- alignment: Alignment.topLeft,
- padding: EdgeInsets.zero,
- ),
- BubbleRotation(
- key: UniqueKey(),
- duration: 2500,
- alignment: Alignment.topRight,
- padding: EdgeInsets.all(6.px),
- ),
- const BubbleContent(),
- ]);
- }
- }
- class BubbleContent extends StatefulWidget {
- const BubbleContent({Key? key}) : super(key: key);
- @override
- State<BubbleContent> createState() => _BubbleContentState();
- }
- class _BubbleContentState extends State<BubbleContent> {
- late FastBean fastBean;
- late Timer timer;
- late String hourMinute;
- late String second;
- int type = 0;
- @override
- void initState() {
- calulate();
- timer = Timer.periodic(const Duration(seconds: 1), (t) {
- calulate();
- });
- super.initState();
- }
- @override
- void dispose() {
- timer.cancel();
- super.dispose();
- }
- void calulate() {
- fastBean = Global().currentFast!;
- int seconds =
- fastBean.startTime! - serverTime().millisecondsSinceEpoch ~/ 1000;
- int hours = seconds ~/ 3600;
- int minutes = seconds % 3600 ~/ 60;
- int sec = (seconds % 60).floor();
- // seconds = 8;
- setState(() {
- if (seconds >= 60) {
- type = 0;
- hourMinute = hours.toString().padLeft(2, '0') +
- ':' +
- minutes.toString().padLeft(2, '0');
- second = sec.toString().padLeft(2, '0');
- } else if (seconds >= 10) {
- type = 1;
- second = sec.toString();
- } else {
- type = 2;
- second = sec.toString();
- if (sec==0){
- Global().homePage.eatEnd();
- }
- }
- });
- }
- DateTime serverTime() {
- int milliseconds = DateTime.now().millisecondsSinceEpoch;
- milliseconds = milliseconds + Global().timeSeconds * 1000;
- return DateTime.fromMillisecondsSinceEpoch(milliseconds);
- }
- @override
- Widget build(BuildContext context) {
- return Container(
- width: 300.px,
- height: 300.px,
- alignment: Alignment.center,
- child: Container(
- width: 260.px,
- height: 260.px,
- alignment: Alignment.center,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(260.px)),
- color: const Color(0xffFF9B00)),
- child: Column(
- children: [
- if (type != 2)
- Container(
- margin: EdgeInsets.only(top: type == 0 ? 57.px : 76.px),
- child: Text(
- '距下次断食开始还剩',
- style: TextStyle(
- color: Colors.white, fontSize: 12.px, height: 1.0),
- ),
- ),
- if (type == 0)
- Container(
- margin: EdgeInsets.only(top: 6.px),
- foregroundDecoration: const BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topCenter,
- end: Alignment.bottomCenter,
- colors: [Color(0x80FF9B00), Color(0x00FF9B00)])),
- child: Text(
- hourMinute,
- style: TextStyle(
- color: Colors.white,
- fontFamily: 'Fast',
- height: 1.0,
- fontSize: 40.px),
- ),
- ),
- Container(
- margin: EdgeInsets.only(top: type==0?0.0:type==2?80.px:10.px),
- child: Text(
- second,
- style: TextStyle(
- color: Colors.white,
- fontFamily: 'Fast',
- height: 1.0,
- fontSize: type == 2 ? 120.px : 80.px),
- ),)
-
- ],
- ),
- ));
- }
- }
- // ignore: must_be_immutable
- class BubbleRotation extends StatefulWidget {
- int duration;
- AlignmentGeometry alignment;
- EdgeInsets padding;
- BubbleRotation(
- {Key? key,
- required this.duration,
- required this.alignment,
- required this.padding})
- : super(key: key);
- @override
- _BubbleRotationState createState() => _BubbleRotationState();
- }
- class _BubbleRotationState extends State<BubbleRotation>
- with SingleTickerProviderStateMixin {
- AnimationController? controller;
- @override
- void initState() {
- super.initState();
- controller = AnimationController(
- vsync: this, duration: Duration(milliseconds: widget.duration));
- controller!.addStatusListener((status) {
- if (status == AnimationStatus.completed) {
- controller!.reset();
- controller!.forward();
- } else if (status == AnimationStatus.dismissed) {}
- });
- controller!.forward();
- }
- @override
- void dispose() {
- controller!.dispose();
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return RotationTransition(
- turns: controller!,
- alignment: Alignment.center,
- child: Container(
- width: 300.px,
- height: 300.px,
- alignment: widget.alignment,
- padding: widget.padding,
- child: Container(
- width: 260.px,
- height: 260.px,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.all(Radius.circular(260.px)),
- color: const Color(0x75FF9B00))),
- ),
- );
- }
- }
|