@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
6
6
import 'package:velocity_x/velocity_x.dart' ;
7
7
8
8
import '../utils/utils_barrel.dart' ;
9
+ import '../widgets/vertical_time_slider.dart' ;
9
10
10
11
class TimerView extends StatefulWidget {
11
12
const TimerView ({super .key});
@@ -19,6 +20,7 @@ class _TimerViewState extends State<TimerView> {
19
20
Duration _lastUsedDuration = kDefaultDuration;
20
21
Duration _duration = kDefaultDuration;
21
22
TimerState _timerState = TimerState .stopped;
23
+ int _sliderValue = kDefaultDuration.inMinutes;
22
24
23
25
final _player = AudioPlayer ();
24
26
final _playerAssetSource = AssetSource ('sounds/wrist-watch-beep.mp3' );
@@ -87,104 +89,133 @@ class _TimerViewState extends State<TimerView> {
87
89
Widget build (BuildContext context) {
88
90
return Material (
89
91
color: kBackgroundColor,
90
- child: < Widget > [
91
- SizedBox (
92
- height: 20 ,
93
- child: Row (
94
- children: List .generate (
95
- 240 ,
96
- (index) {
97
- final isInvisible = index % 2 != 0 ;
98
- final twentyFiveIndicator = index == 50 ;
99
-
100
- return Container (
101
- width: twentyFiveIndicator ? 1.5 : 1 ,
102
- height: 20 ,
103
- color: isInvisible
104
- ? Colors .transparent
105
- : twentyFiveIndicator
106
- ? kForegroundColor
107
- : kTimeSliderInactiveColor,
108
- );
109
- },
110
- ),
111
- ),
112
- ),
113
- const SizedBox (height: 16 ),
114
- Row (
115
- children: [
116
- _buildSuggestionButtons (
117
- '5m' ,
118
- () {
119
- setState (() {
120
- _duration = const Duration (minutes: 5 );
121
- _startTimer ();
122
- });
123
- },
124
- ),
125
- const SizedBox (width: 18 ),
126
- _buildSuggestionButtons (
127
- '15m' ,
128
- () {
129
- setState (() {
130
- _duration = const Duration (minutes: 15 );
131
- _startTimer ();
132
- });
133
- },
134
- ),
135
- const SizedBox (width: 18 ),
136
- _buildSuggestionButtons (
137
- '25m' ,
138
- () {
139
- setState (() {
140
- _duration = const Duration (minutes: 25 );
141
- _startTimer ();
142
- });
143
- },
144
- ),
145
- const Spacer (),
146
- CupertinoButton (
147
- child: const Icon (
148
- CupertinoIcons .ellipsis,
149
- size: 12 ,
150
- color: Color (0xFF9DA3A7 ),
92
+ child: Padding (
93
+ padding: const EdgeInsets .all (12 ),
94
+ child: Column (
95
+ children: < Widget > [
96
+ SizedBox (
97
+ // For safety only
98
+ height: kSliderHeight,
99
+ child: LayoutBuilder (
100
+ builder: (_, constraints) {
101
+ final width = constraints.maxWidth.floor ();
102
+
103
+ return GestureDetector (
104
+ behavior: HitTestBehavior .opaque,
105
+ onHorizontalDragUpdate: (details) {
106
+ if (details.localPosition.dx > width + 20 ) {
107
+ return ;
108
+ }
109
+ setState (() {
110
+ _sliderValue = ((details.localPosition.dx).clamp (0 , width - 1 ) / 2 ).floor ();
111
+ _duration = Duration (minutes: _sliderValue);
112
+ });
113
+ },
114
+ onTapDown: (details) {
115
+ setState (() {
116
+ _sliderValue = ((details.localPosition.dx).clamp (0 , width - 1 ) / 2 ).floor ();
117
+ _duration = Duration (minutes: _sliderValue);
118
+ });
119
+ },
120
+ child: Stack (
121
+ alignment: Alignment .center,
122
+ children: [
123
+ // Slider Base
124
+ const IgnorePointer (
125
+ child: VerticalTimeSlider (),
126
+ ),
127
+ // Indicator
128
+ Positioned (
129
+ left: _sliderValue.toDouble () * 2 ,
130
+ child: Container (
131
+ height: kSliderHeight,
132
+ width: kActiveSliderWidth,
133
+ color: kForegroundColor,
134
+ ),
135
+ ),
136
+ ],
137
+ ),
138
+ );
139
+ },
151
140
),
152
- minSize: 0 ,
153
- padding: EdgeInsets .zero,
154
- onPressed: () {},
155
141
),
156
- ],
157
- ),
158
- const Spacer (),
159
- Row (
160
- crossAxisAlignment: CrossAxisAlignment .end,
161
- children: [
162
- CupertinoButton (
163
- child: () {
164
- if (_timerState == TimerState .running) {
165
- return 'stop' ;
166
- }
167
- return 'start' ;
168
- }()
169
- .text
170
- .size (13 )
171
- .color (kForegroundColor)
172
- .make (),
173
- padding: EdgeInsets .zero,
174
- minSize: 0 ,
175
- onPressed: () async {
176
- if (_timerState == TimerState .running) {
177
- _cancelTimer (TimerState .stopped);
178
- } else {
179
- _startTimer ();
180
- }
181
- },
142
+ const SizedBox (height: 16 ),
143
+ Row (
144
+ children: [
145
+ _buildSuggestionButtons (
146
+ '5m' ,
147
+ () {
148
+ setState (() {
149
+ _duration = const Duration (minutes: 5 );
150
+ _startTimer ();
151
+ });
152
+ },
153
+ ),
154
+ const SizedBox (width: 16 ),
155
+ _buildSuggestionButtons (
156
+ '15m' ,
157
+ () {
158
+ setState (() {
159
+ _duration = const Duration (minutes: 15 );
160
+ _startTimer ();
161
+ });
162
+ },
163
+ ),
164
+ const SizedBox (width: 16 ),
165
+ _buildSuggestionButtons (
166
+ '25m' ,
167
+ () {
168
+ setState (() {
169
+ _duration = const Duration (minutes: 25 );
170
+ _startTimer ();
171
+ });
172
+ },
173
+ ),
174
+ const Spacer (),
175
+ CupertinoButton (
176
+ child: const Icon (
177
+ CupertinoIcons .ellipsis,
178
+ size: 12 ,
179
+ color: Color (0xFF9DA3A7 ),
180
+ ),
181
+ minSize: 0 ,
182
+ padding: EdgeInsets .zero,
183
+ onPressed: () {},
184
+ ),
185
+ ],
182
186
),
183
187
const Spacer (),
184
- _duration.formatToMMss ().text.size (32 ).light.color (kForegroundColor).make (),
188
+ Row (
189
+ crossAxisAlignment: CrossAxisAlignment .end,
190
+ children: [
191
+ CupertinoButton (
192
+ child: () {
193
+ if (_timerState == TimerState .running) {
194
+ return 'stop' ;
195
+ }
196
+ return 'start' ;
197
+ }()
198
+ .text
199
+ .size (13 )
200
+ .color (kForegroundColor)
201
+ .make (),
202
+ padding: EdgeInsets .zero,
203
+ minSize: 0 ,
204
+ onPressed: () async {
205
+ if (_timerState == TimerState .running) {
206
+ _cancelTimer (TimerState .stopped);
207
+ } else {
208
+ _startTimer ();
209
+ }
210
+ },
211
+ ),
212
+ const Spacer (),
213
+ _duration.formatToHHMMss ().text.size (32 ).light.color (kForegroundColor).make (),
214
+ ],
215
+ ),
185
216
],
186
217
),
187
- ]. vStack (). p8 ( ),
218
+ ),
188
219
);
189
220
}
190
221
0 commit comments