Line data Source code
1 : import 'package:flutter/material.dart';
2 : import 'package:google_fonts/google_fonts.dart';
3 : import 'package:mvvm_builder/mvvm_builder.dart';
4 : import 'package:pal/src/ui/client/helpers/simple_helper/simple_helper_presenter.dart';
5 : import 'package:pal/src/ui/client/helpers/simple_helper/simple_helper_viewmodel.dart';
6 : import 'package:pal/src/ui/client/widgets/animated/animated_translate.dart';
7 : import 'package:pal/src/ui/shared/widgets/circle_button.dart';
8 :
9 : import '../../../shared/helper_shared_viewmodels.dart';
10 :
11 : abstract class SimpleHelperView {}
12 :
13 : class SimpleHelperPage extends StatelessWidget implements SimpleHelperView {
14 : final HelperTextViewModel descriptionLabel;
15 : final HelperBoxViewModel helperBoxViewModel;
16 :
17 1 : SimpleHelperPage({
18 : Key key,
19 : @required this.descriptionLabel,
20 : @required this.helperBoxViewModel,
21 0 : }) : assert(helperBoxViewModel != null),
22 0 : assert(descriptionLabel != null);
23 :
24 : final _mvvmPageBuilder =
25 : MVVMPageBuilder<SimpleHelperPresenter, SimpleHelperModel>();
26 :
27 1 : @override
28 : Widget build(BuildContext context) {
29 2 : return _mvvmPageBuilder.build(
30 1 : key: UniqueKey(),
31 : context: context,
32 2 : presenterBuilder: (context) => SimpleHelperPresenter(this),
33 1 : builder: (mvvmContext, presenter, model) {
34 1 : final Animation<double> offsetAnimation = Tween(begin: 0.0, end: 20.0)
35 2 : .chain(CurveTween(curve: Curves.elasticIn))
36 3 : .animate(mvvmContext.animationsControllers[2]);
37 :
38 1 : return AnimatedTranslateWidget(
39 1 : position: Tween<Offset>(
40 1 : begin: Offset(0.0, 1.0),
41 1 : end: Offset(0.0, 0.0),
42 : ),
43 2 : animationController: mvvmContext.animationsControllers[0],
44 1 : widget: SafeArea(
45 1 : child: Column(
46 1 : children: [
47 1 : AnimatedBuilder(
48 : animation: offsetAnimation,
49 1 : builder: (context, child) {
50 1 : return Transform.translate(
51 2 : offset: Offset(offsetAnimation.value, 0.0),
52 1 : child: Container(
53 3 : width: MediaQuery.of(context).size.width,
54 1 : decoration: BoxDecoration(
55 2 : color: this.helperBoxViewModel?.backgroundColor,
56 : borderRadius:
57 2 : BorderRadius.all(Radius.circular(8.0)),
58 1 : boxShadow: [
59 1 : BoxShadow(
60 : color: Colors.black26,
61 1 : offset: Offset(0, 8),
62 : blurRadius: 8,
63 : spreadRadius: 2,
64 : ),
65 : ],
66 : ),
67 1 : child: Padding(
68 1 : padding: EdgeInsets.symmetric(
69 : horizontal: 8,
70 : vertical: 16,
71 : ),
72 1 : child: Row(
73 : mainAxisAlignment: MainAxisAlignment.spaceBetween,
74 : mainAxisSize: MainAxisSize.max,
75 1 : children: <Widget>[
76 1 : _buildLeft(mvvmContext),
77 1 : _buildContent(),
78 1 : _buildRight(mvvmContext),
79 : ],
80 : ),
81 : ),
82 : ),
83 : );
84 : }),
85 1 : SizedBox(height: 5.0),
86 1 : Text(
87 : '💡 You can swipe to dismiss the helper.',
88 1 : style: TextStyle(
89 : fontSize: 12.0,
90 : color: Colors.white,
91 : ),
92 : ),
93 : ],
94 : ),
95 : ),
96 : );
97 : },
98 1 : multipleAnimControllerBuilder: (tickerProvider) {
99 1 : return [
100 : // Box transition
101 1 : AnimationController(
102 : vsync: tickerProvider,
103 1 : duration: Duration(
104 : milliseconds: 1100,
105 : ),
106 : ),
107 : // Thumb
108 1 : AnimationController(
109 : vsync: tickerProvider,
110 1 : duration: Duration(
111 : milliseconds: 500,
112 : ),
113 : ),
114 : // Shake
115 1 : AnimationController(
116 : vsync: tickerProvider,
117 1 : duration: Duration(
118 : milliseconds: 500,
119 : ),
120 : ),
121 : ];
122 : },
123 0 : animListener: (context, presenter, model) {
124 0 : if (model.boxTransitionAnimation) {
125 0 : context.animationsControllers[0].forward().then(
126 0 : (value) => presenter.onBoxAnimationEnd(),
127 : );
128 : }
129 0 : if (model.thumbAnimation) {
130 0 : context.animationsControllers[1].repeat(reverse: true).then(
131 0 : (value) => presenter.onThumbAnimationEnd(),
132 : );
133 : }
134 0 : if (model.shakeAnimation) {
135 0 : context.animationsControllers[2].forward().then(
136 0 : (value) {
137 0 : presenter.onShakeAnimationEnd();
138 0 : context.animationsControllers[2].reverse();
139 : },
140 : );
141 : }
142 : },
143 : );
144 : }
145 :
146 1 : Widget _buildLeft(MvvmContext mvvmContext) {
147 1 : return Transform.translate(
148 2 : offset: Offset(-25.0, 0),
149 1 : child: CircleIconButton(
150 : backgroundColor: Colors.redAccent,
151 1 : icon: Icon(
152 : Icons.thumb_down,
153 : color: Colors.white,
154 : size: 15,
155 : ),
156 0 : onTapCallback: () {},
157 : ),
158 : );
159 : }
160 :
161 1 : Widget _buildRight(MvvmContext mvvmContext) {
162 1 : return Transform.translate(
163 1 : offset: Offset(25.0, 0),
164 1 : child: CircleIconButton(
165 : backgroundColor: Colors.greenAccent,
166 1 : icon: Icon(
167 : Icons.thumb_up,
168 : color: Colors.white,
169 : size: 15,
170 : ),
171 0 : onTapCallback: () {},
172 : ),
173 : );
174 : }
175 :
176 1 : Flexible _buildContent() {
177 1 : return Flexible(
178 : flex: 10,
179 1 : child: Padding(
180 : padding: const EdgeInsets.symmetric(horizontal: 8.0),
181 1 : child: Column(
182 : crossAxisAlignment: CrossAxisAlignment.start,
183 1 : children: <Widget>[
184 1 : Padding(
185 : padding: const EdgeInsets.only(top: 4.0),
186 1 : child: Text(
187 2 : descriptionLabel?.text ?? '',
188 : textAlign: TextAlign.center,
189 1 : style: TextStyle(
190 2 : color: descriptionLabel.fontColor ?? Colors.white,
191 2 : fontSize: descriptionLabel.fontSize ?? 14.0,
192 2 : fontWeight: descriptionLabel.fontWeight ?? FontWeight.normal,
193 1 : ).merge(
194 1 : GoogleFonts.getFont(
195 2 : descriptionLabel?.fontFamily ?? 'Montserrat'),
196 : ),
197 : maxLines: 10,
198 : ),
199 : ),
200 : ],
201 : ),
202 : ),
203 : );
204 : }
205 : }
|