Skip to content

Commit 10eb1db

Browse files
committed
fix: seek throttle
1 parent ce44e9a commit 10eb1db

6 files changed

Lines changed: 64 additions & 17 deletions

File tree

changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This project loosely follows Keep a Changelog and uses Semantic Versioning.
1010

1111
### Fixed
1212

13+
- Call backend only on drag end to prevent seek throttle
1314
- All button now should has pointer now
1415
- Discord button label overflow
1516
- Added helpers to prevent backend crash

lib/providers/player_provider.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,19 @@ class PlayerNotifier extends StateNotifier<PlayerState> {
192192
}
193193
}
194194

195+
void seekPreview(Duration position) {
196+
state = state.copyWith(position: position);
197+
}
198+
199+
Future<void> seekCommit(Duration position) async {
200+
final sec = position.inMilliseconds / 1000.0;
201+
await AudioService.seek(sec);
202+
state = state.copyWith(position: position);
203+
if (state.status == PlayerStatus.playing) {
204+
DiscordService.updateAfterSeek(state, sec);
205+
}
206+
}
207+
195208
Future<void> setVolume(double volume) async {
196209
final v = volume.clamp(0.0, 1.0);
197210
await AudioService.setVolume(v);

lib/widgets/custom_slider.dart

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
33
class CustomSlider extends StatefulWidget {
44
final double value;
55
final ValueChanged<double>? onChanged;
6+
final ValueChanged<double>? onChangeEnd;
67
final double trackHeight;
78
final double thumbRadius;
89
final bool showThumb;
@@ -14,6 +15,7 @@ class CustomSlider extends StatefulWidget {
1415
super.key,
1516
required this.value,
1617
this.onChanged,
18+
this.onChangeEnd,
1719
this.trackHeight = 2,
1820
this.thumbRadius = 5,
1921
this.showThumb = true,
@@ -28,19 +30,32 @@ class CustomSlider extends StatefulWidget {
2830

2931
class _CustomSliderState extends State<CustomSlider> {
3032
bool _dragging = false;
33+
double _dragValue = 0.0;
3134

3235
void _handleTapDown(TapDownDetails d, double width) {
3336
if (widget.onChanged == null) return;
3437
final v = (d.localPosition.dx / width).clamp(0.0, 1.0);
3538
widget.onChanged!(v);
39+
widget.onChangeEnd?.call(v);
3640
}
3741

38-
void _handleDrag(DragUpdateDetails d, double width) {
42+
void _handleDragStart(DragStartDetails d, double width) {
43+
_dragValue = (d.localPosition.dx / width).clamp(0.0, 1.0);
44+
setState(() => _dragging = true);
45+
}
46+
47+
void _handleDragUpdate(DragUpdateDetails d, double width) {
3948
if (widget.onChanged == null) return;
4049
final v = (d.localPosition.dx / width).clamp(0.0, 1.0);
50+
_dragValue = v;
4151
widget.onChanged!(v);
4252
}
4353

54+
void _handleDragEnd(DragEndDetails _) {
55+
setState(() => _dragging = false);
56+
widget.onChangeEnd?.call(_dragValue);
57+
}
58+
4459
@override
4560
Widget build(BuildContext context) {
4661
final cs = Theme.of(context).colorScheme;
@@ -55,9 +70,9 @@ class _CustomSliderState extends State<CustomSlider> {
5570
return GestureDetector(
5671
behavior: HitTestBehavior.opaque,
5772
onTapDown: (d) => _handleTapDown(d, w),
58-
onHorizontalDragStart: (_) => setState(() => _dragging = true),
59-
onHorizontalDragUpdate: (d) => _handleDrag(d, w),
60-
onHorizontalDragEnd: (_) => setState(() => _dragging = false),
73+
onHorizontalDragStart: (d) => _handleDragStart(d, w),
74+
onHorizontalDragUpdate: (d) => _handleDragUpdate(d, w),
75+
onHorizontalDragEnd: _handleDragEnd,
6176
child: SizedBox(
6277
height: widget.thumbRadius * 2 + 8,
6378
child: CustomPaint(
@@ -99,7 +114,6 @@ class _SliderPainter extends CustomPainter {
99114
@override
100115
void paint(Canvas canvas, Size size) {
101116
final cy = size.height / 2;
102-
final trackY = cy;
103117
final left = thumbRadius;
104118
final right = size.width - thumbRadius;
105119
final trackW = right - left;
@@ -117,17 +131,13 @@ class _SliderPainter extends CustomPainter {
117131
..strokeWidth = trackHeight
118132
..style = PaintingStyle.stroke;
119133

120-
// inactive track
121-
canvas.drawLine(Offset(left, trackY), Offset(right, trackY), trackPaint);
122-
// active track
134+
canvas.drawLine(Offset(left, cy), Offset(right, cy), trackPaint);
123135
if (fillX > left) {
124-
canvas.drawLine(Offset(left, trackY), Offset(fillX, trackY), fillPaint);
136+
canvas.drawLine(Offset(left, cy), Offset(fillX, cy), fillPaint);
125137
}
126-
127-
// thumb
128138
if (showThumb) {
129139
canvas.drawCircle(
130-
Offset(fillX, trackY),
140+
Offset(fillX, cy),
131141
thumbRadius,
132142
Paint()..color = thumbColor,
133143
);

lib/widgets/mini_player_bar.dart

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,12 @@ class _DesktopBar extends ConsumerWidget {
240240
inactiveColor: cs.onSurface.withValues(alpha: 0.08),
241241
onChanged: (v) {
242242
if (duration.inMilliseconds > 0) {
243-
notifier.seek(duration * v);
243+
notifier.seekPreview(duration * v);
244+
}
245+
},
246+
onChangeEnd: (v) {
247+
if (duration.inMilliseconds > 0) {
248+
notifier.seekCommit(duration * v);
244249
}
245250
},
246251
),
@@ -432,7 +437,12 @@ class _DesktopBar extends ConsumerWidget {
432437
inactiveColor: cs.onSurface.withValues(alpha: 0.08),
433438
onChanged: (v) {
434439
if (duration.inMilliseconds > 0) {
435-
notifier.seek(duration * v);
440+
notifier.seekPreview(duration * v);
441+
}
442+
},
443+
onChangeEnd: (v) {
444+
if (duration.inMilliseconds > 0) {
445+
notifier.seekCommit(duration * v);
436446
}
437447
},
438448
),
@@ -536,7 +546,12 @@ class _MobileBar extends ConsumerWidget {
536546
activeColor: cs.onSurface.withValues(alpha: 0.36),
537547
inactiveColor: cs.onSurface.withValues(alpha: 0.08),
538548
onChanged: (v) {
539-
if (duration.inMilliseconds > 0) notifier.seek(duration * v);
549+
if (duration.inMilliseconds > 0)
550+
notifier.seekPreview(duration * v);
551+
},
552+
onChangeEnd: (v) {
553+
if (duration.inMilliseconds > 0)
554+
notifier.seekCommit(duration * v);
540555
},
541556
),
542557
Padding(

lib/widgets/player_controls.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,14 @@ class PlayerControls extends ConsumerWidget {
3939
? null
4040
: (v) {
4141
if (duration.inMilliseconds > 0) {
42-
notifier.seek(duration * v.clamp(0.0, 1.0));
42+
notifier.seekPreview(duration * v.clamp(0.0, 1.0));
43+
}
44+
},
45+
onChangeEnd: player.currentTrack == null
46+
? null
47+
: (v) {
48+
if (duration.inMilliseconds > 0) {
49+
notifier.seekCommit(duration * v.clamp(0.0, 1.0));
4350
}
4451
},
4552
),

linux/xyz.nokarin.aqloss.metainfo.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@
5353
<release version="0.2.2" date="2026-05-17">
5454
<url type="details">https://github.com/nokarin-dev/aqloss/releases/tag/v0.2.2</url>
5555
<description>
56-
<p>Added helpers, fix discord button label overflow, cursor pointer.</p>
56+
<p>Added helpers, fix discord button label overflow, cursor pointer, seek throttle, and more.</p>
5757
<ul>
58+
<li>Call backend only on drag end to prevent seek throttle</li>
5859
<li>All button now should has pointer now</li>
5960
<li>Discord button label overflow</li>
6061
<li>Added helpers to prevent backend crash</li>

0 commit comments

Comments
 (0)