import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:aitrainer_app/library/super_tooltip.dart'; class TutorialWidget with Trans, Logging { static final TutorialWidget _singleton = TutorialWidget._internal(); SuperTooltip? tooltip; TutorialWidget._internal(); factory TutorialWidget() { return _singleton; } void close() { if (tooltip != null && tooltip!.isOpen) { tooltip!.close(); } } Widget explanationFrame(Widget widget) { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(24), boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)], image: DecorationImage( image: AssetImage('asset/image/WT_plainblack_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), ), child: widget, ); } void explanation(BuildContext context, Widget widget) { final height = MediaQuery.of(context).size.height; print("Height $height"); tooltip = SuperTooltip( top: height < 800 ? 60 : 120, left: 20, right: 20, backgroundColor: Colors.black87, popupDirection: TooltipDirection.up, maxWidth: 330, borderColor: Colors.transparent, borderWidth: 1.0, minimumOutSidePadding: 20, //snapsFarAwayVertically: false, showCloseButton: ShowCloseButton.outside, closeButtonColor: Colors.grey, dismissOnTapOutside: true, outsideBackgroundColor: Colors.black.withOpacity(0.6), hasShadow: true, touchThrougArea: null, //onClose: () => bloc.add(TutorialFinished()), custom: true, content: explanationFrame(widget)); tooltip!.showBox(context); } void tip(BuildContext context) { final TutorialBloc bloc = BlocProvider.of(context); if (bloc.action == null) { print("Action is null"); return; } if (bloc.actualCheck == "directTest") { print("DirectTest"); tooltip!.close(); directTest(bloc); return; } setContext(context); if (tooltip != null && tooltip!.isOpen) { tooltip!.rebuild(); } var renderBox = context.findRenderObject() as RenderBox; final overlay = Overlay.of(context)!.context.findRenderObject() as RenderBox?; var targetGlobalCenter = renderBox.localToGlobal(renderBox.size.center(Offset.zero), ancestor: overlay); final double mediaSize = MediaQuery.of(context).size.width; final double mediaHeight = MediaQuery.of(context).size.height; final Rect? area = bloc.action!.showBubble == true ? Rect.fromLTWH(mediaSize / 2 - 220, targetGlobalCenter.dy - bloc.action!.bubbleY, bloc.action!.bubbleWidth.toDouble(), bloc.action!.bubbleHeight.toDouble()) //? Rect.fromLTWH(targetGlobalCenter.dx - 60, targetGlobalCenter.dy + 120, 420, 320) //: Rect.fromLTWH(0, 0, 100, 100); : null; final double distortion = mediaHeight / bloc.mediaHeightBase; double fontSize = 14; if (mediaSize > 800) { fontSize = 16; } else if (mediaSize < 600) { fontSize = 13; } double calculatedTop = bloc.top != null ? bloc.top! : 20.0; if (calculatedTop < 0) { calculatedTop = 10; } print("Height: $mediaHeight, width: $mediaSize distortion: $distortion top: ${bloc.top!} calculated $calculatedTop"); print("targetCenter X ${targetGlobalCenter.dx} - Y: ${targetGlobalCenter.dy}"); tooltip = SuperTooltip( top: calculatedTop, left: bloc.left, backgroundColor: Colors.black.withOpacity(0.7), popupDirection: bloc.action == null || bloc.action!.direction == "up" ? TooltipDirection.up : TooltipDirection.down, maxWidth: 390, minWidth: 300, minHeight: 100, maxHeight: 300, borderColor: Colors.orange, borderWidth: 1.0, minimumOutSidePadding: 20, snapsFarAwayVertically: false, showCloseButton: ShowCloseButton.inside, closeButtonColor: Colors.grey, dismissOnTapOutside: false, outsideBackgroundColor: Colors.black.withOpacity(0.6), hasShadow: true, touchThrougArea: area, onClose: () => bloc.add(TutorialFinished()), custom: true, touchThroughAreaShape: ClipAreaShape.oval, content: new Material( color: Colors.transparent, child: Padding( padding: const EdgeInsets.only(top: 20.0), child: Stack(alignment: Alignment.bottomRight, children: [ SingleChildScrollView( child: Html( data: bloc.actualText! + "


", //Optional parameters: style: { "p": Style( color: Colors.white, fontSize: FontSize(fontSize), padding: const EdgeInsets.all(4), ), "li": Style( color: Colors.white, fontSize: FontSize(fontSize), padding: const EdgeInsets.only(left: 4), ), "h2": Style( color: Colors.white, fontWeight: FontWeight.bold, fontSize: FontSize.larger, //padding: const EdgeInsets.all(4), ), "h1": Style( color: Colors.yellow[400], fontWeight: FontWeight.bold, fontSize: FontSize.larger, alignment: Alignment.center, padding: const EdgeInsets.all(4), ), }, )), bloc.showCheckText ? bloc.checks.length > 1 ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, ), onPressed: () => {bloc.add(TutorialNext(text: bloc.checks[0]))}, child: Text("« " + t(bloc.checks[0]), style: GoogleFonts.archivoBlack(color: Colors.orange[400]!, fontSize: fontSize)), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, ), onPressed: () => {bloc.add(TutorialNext(text: bloc.checks[1]))}, child: Text(t(bloc.checks[1]) + " »", style: GoogleFonts.archivoBlack(color: Colors.orange[400]!, fontSize: fontSize)), ), ], ) : ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, ), onPressed: () => { //tooltip!.rebuild(context), bloc.add(TutorialNext(text: bloc.checks[0])), }, child: Text(t(bloc.checks[0]) + " »", style: GoogleFonts.archivoBlack(color: Colors.orange[400]!, fontSize: fontSize)), ) : Offstage(), ]), )), ); tooltip!.show(context); } void directTest(TutorialBloc bloc) { ExerciseType? exerciseType; showCupertinoDialog( useRootNavigator: true, context: context, builder: (_) => CupertinoAlertDialog( title: Html(data: bloc.actualText!, //Optional parameters: style: { "p": Style( color: Colors.indigo, fontSize: FontSize(16), padding: const EdgeInsets.all(4), ), }), content: Column(children: [ Divider(), ]), actions: [ TextButton( child: Text(t("Chest Press")), onPressed: () { Navigator.pop(context); exerciseType = Cache().getExerciseTypeById(37); if (exerciseType != null) { Navigator.of(context).popAndPushNamed('exerciseNewPage', arguments: exerciseType); } }), TextButton( child: Text(t("Olympic Squat")), onPressed: () { Navigator.pop(context); exerciseType = Cache().getExerciseTypeById(145); if (exerciseType != null) { Navigator.of(context).popAndPushNamed('exerciseNewPage', arguments: exerciseType); } }, ), TextButton( child: Text(t("Pushups")), onPressed: () { Navigator.pop(context); exerciseType = Cache().getExerciseTypeById(33); if (exerciseType != null) { Navigator.of(context).popAndPushNamed('exerciseNewPage', arguments: exerciseType); } }, ), TextButton( child: Text(t("Plank")), onPressed: () { Navigator.pop(context); exerciseType = Cache().getExerciseTypeById(53); if (exerciseType != null) { Navigator.of(context).popAndPushNamed('exerciseNewPage', arguments: exerciseType); } }, ) ], )); } }