Skip to content

Commit 14be935

Browse files
committed
refactor: move position slider into a separate file
1 parent 50d9af2 commit 14be935

File tree

2 files changed

+112
-88
lines changed

2 files changed

+112
-88
lines changed

lib/screens/now_playing_page.dart

Lines changed: 1 addition & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,15 @@ import 'package:flutter_flip_card/flutter_flip_card.dart';
2626
import 'package:musify/API/musify.dart';
2727
import 'package:musify/extensions/l10n.dart';
2828
import 'package:musify/main.dart';
29-
import 'package:musify/models/position_data.dart';
3029
import 'package:musify/services/settings_manager.dart';
3130
import 'package:musify/utilities/common_variables.dart';
3231
import 'package:musify/utilities/flutter_bottom_sheet.dart';
3332
import 'package:musify/utilities/flutter_toast.dart';
34-
import 'package:musify/utilities/formatter.dart';
3533
import 'package:musify/utilities/mediaitem.dart';
3634
import 'package:musify/utilities/utils.dart';
3735
import 'package:musify/widgets/marque.dart';
3836
import 'package:musify/widgets/playback_icon_button.dart';
37+
import 'package:musify/widgets/position_slider.dart';
3938
import 'package:musify/widgets/queue_list_view.dart';
4039
import 'package:musify/widgets/song_artwork.dart';
4140
import 'package:musify/widgets/song_bar.dart';
@@ -346,92 +345,6 @@ class NowPlayingControls extends StatelessWidget {
346345
}
347346
}
348347

349-
class PositionSlider extends StatefulWidget {
350-
const PositionSlider({super.key});
351-
352-
@override
353-
State<PositionSlider> createState() => _PositionSliderState();
354-
}
355-
356-
class _PositionSliderState extends State<PositionSlider> {
357-
bool _isDragging = false;
358-
double _dragValue = 0;
359-
360-
@override
361-
Widget build(BuildContext context) {
362-
final primaryColor = Theme.of(context).colorScheme.primary;
363-
364-
return Padding(
365-
padding: const EdgeInsets.symmetric(horizontal: 10),
366-
child: StreamBuilder<PositionData>(
367-
stream: audioHandler.positionDataStream,
368-
builder: (context, snapshot) {
369-
final hasData = snapshot.hasData && snapshot.data != null;
370-
final positionData = hasData
371-
? snapshot.data!
372-
: PositionData(Duration.zero, Duration.zero, Duration.zero);
373-
374-
final maxDuration = positionData.duration.inSeconds > 0
375-
? positionData.duration.inSeconds.toDouble()
376-
: 1.0;
377-
378-
final currentValue = _isDragging
379-
? _dragValue
380-
: positionData.position.inSeconds.toDouble();
381-
382-
return Column(
383-
mainAxisAlignment: MainAxisAlignment.center,
384-
children: [
385-
Slider(
386-
value: currentValue.clamp(0.0, maxDuration),
387-
onChanged: hasData
388-
? (value) {
389-
setState(() {
390-
_isDragging = true;
391-
_dragValue = value;
392-
});
393-
}
394-
: null,
395-
onChangeEnd: hasData
396-
? (value) {
397-
audioHandler.seek(Duration(seconds: value.toInt()));
398-
setState(() {
399-
_isDragging = false;
400-
});
401-
}
402-
: null,
403-
max: maxDuration,
404-
),
405-
_buildPositionRow(context, primaryColor, positionData),
406-
],
407-
);
408-
},
409-
),
410-
);
411-
}
412-
413-
Widget _buildPositionRow(
414-
BuildContext context,
415-
Color fontColor,
416-
PositionData positionData,
417-
) {
418-
final positionText = formatDuration(positionData.position.inSeconds);
419-
final durationText = formatDuration(positionData.duration.inSeconds);
420-
final textStyle = TextStyle(fontSize: 15, color: fontColor);
421-
422-
return Padding(
423-
padding: const EdgeInsets.symmetric(horizontal: 22),
424-
child: Row(
425-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
426-
children: [
427-
Text(positionText, style: textStyle),
428-
Text(durationText, style: textStyle),
429-
],
430-
),
431-
);
432-
}
433-
}
434-
435348
class PlayerControlButtons extends StatelessWidget {
436349
const PlayerControlButtons({
437350
super.key,

lib/widgets/position_slider.dart

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (C) 2025 Valeri Gokadze
3+
*
4+
* Musify is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* Musify is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*
17+
*
18+
* For more information about Musify, including how to contribute,
19+
* please visit: https://github.com/gokadzev/Musify
20+
*/
21+
22+
import 'package:flutter/material.dart';
23+
import 'package:musify/main.dart';
24+
import 'package:musify/models/position_data.dart';
25+
import 'package:musify/utilities/formatter.dart';
26+
27+
class PositionSlider extends StatefulWidget {
28+
const PositionSlider({super.key});
29+
30+
@override
31+
State<PositionSlider> createState() => _PositionSliderState();
32+
}
33+
34+
class _PositionSliderState extends State<PositionSlider> {
35+
bool _isDragging = false;
36+
double _dragValue = 0;
37+
38+
@override
39+
Widget build(BuildContext context) {
40+
final primaryColor = Theme.of(context).colorScheme.primary;
41+
42+
return Padding(
43+
padding: const EdgeInsets.symmetric(horizontal: 10),
44+
child: StreamBuilder<PositionData>(
45+
stream: audioHandler.positionDataStream,
46+
builder: (context, snapshot) {
47+
final hasData = snapshot.hasData && snapshot.data != null;
48+
final positionData = hasData
49+
? snapshot.data!
50+
: PositionData(Duration.zero, Duration.zero, Duration.zero);
51+
52+
final maxDuration = positionData.duration.inSeconds > 0
53+
? positionData.duration.inSeconds.toDouble()
54+
: 1.0;
55+
56+
final currentValue = _isDragging
57+
? _dragValue
58+
: positionData.position.inSeconds.toDouble();
59+
60+
return Column(
61+
mainAxisAlignment: MainAxisAlignment.center,
62+
children: [
63+
Slider(
64+
value: currentValue.clamp(0.0, maxDuration),
65+
onChanged: hasData
66+
? (value) {
67+
setState(() {
68+
_isDragging = true;
69+
_dragValue = value;
70+
});
71+
}
72+
: null,
73+
onChangeEnd: hasData
74+
? (value) {
75+
audioHandler.seek(Duration(seconds: value.toInt()));
76+
setState(() {
77+
_isDragging = false;
78+
});
79+
}
80+
: null,
81+
max: maxDuration,
82+
),
83+
_buildPositionRow(context, primaryColor, positionData),
84+
],
85+
);
86+
},
87+
),
88+
);
89+
}
90+
91+
Widget _buildPositionRow(
92+
BuildContext context,
93+
Color fontColor,
94+
PositionData positionData,
95+
) {
96+
final positionText = formatDuration(positionData.position.inSeconds);
97+
final durationText = formatDuration(positionData.duration.inSeconds);
98+
final textStyle = TextStyle(fontSize: 15, color: fontColor);
99+
100+
return Padding(
101+
padding: const EdgeInsets.symmetric(horizontal: 22),
102+
child: Row(
103+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
104+
children: [
105+
Text(positionText, style: textStyle),
106+
Text(durationText, style: textStyle),
107+
],
108+
),
109+
);
110+
}
111+
}

0 commit comments

Comments
 (0)