mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-26 12:52:40 +02:00
fix(player): smooth timed lyrics highlighting
This commit is contained in:
@@ -24,11 +24,14 @@ void main() {
|
||||
}
|
||||
final arguments = (call.arguments as Map).cast<String, dynamic>();
|
||||
final path = arguments['file_path']?.toString() ?? '';
|
||||
final lyrics = path.endsWith('/timed.flac')
|
||||
? '''<tt xmlns="http://www.w3.org/ns/ttml"><body><div><p begin="00:00.000" end="00:02.000"><span begin="00:00.000">Short</span></p></div></body></tt>'''
|
||||
: path.endsWith('/second.flac')
|
||||
? '[00:01.00]Second lyric'
|
||||
: '[00:01.00]First lyric';
|
||||
return jsonEncode({
|
||||
'title': path.endsWith('/second.flac') ? 'Second' : 'First',
|
||||
'lyrics': path.endsWith('/second.flac')
|
||||
? '[00:01.00]Second lyric'
|
||||
: '[00:01.00]First lyric',
|
||||
'lyrics': lyrics,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -89,6 +92,21 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('short timed lyric remains horizontally centered', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpNowPlaying(tester);
|
||||
|
||||
mediaItems.add(item('timed'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.drag(find.byType(PageView), const Offset(-700, 0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final lyric = find.bySemanticsLabel('Short');
|
||||
expect(lyric, findsOneWidget);
|
||||
expect(tester.getCenter(lyric).dx, closeTo(540, 1));
|
||||
});
|
||||
|
||||
testWidgets('Now Playing menu exposes Go to Album when album is known', (
|
||||
tester,
|
||||
) async {
|
||||
|
||||
@@ -27,4 +27,113 @@ void main() {
|
||||
24,
|
||||
);
|
||||
});
|
||||
|
||||
test('advances at the exact next line boundary', () {
|
||||
const starts = [
|
||||
Duration(seconds: 1),
|
||||
Duration(seconds: 3),
|
||||
Duration(seconds: 3),
|
||||
Duration(seconds: 6),
|
||||
];
|
||||
|
||||
expect(
|
||||
syncedLyricsDueLineIndex(
|
||||
lineStarts: starts,
|
||||
currentIndex: 0,
|
||||
position: const Duration(milliseconds: 2999),
|
||||
),
|
||||
0,
|
||||
);
|
||||
expect(
|
||||
syncedLyricsDueLineIndex(
|
||||
lineStarts: starts,
|
||||
currentIndex: 0,
|
||||
position: const Duration(seconds: 3),
|
||||
),
|
||||
2,
|
||||
);
|
||||
});
|
||||
|
||||
group('smooth timed lyric highlight', () {
|
||||
test('interpolates position only while playback is advancing', () {
|
||||
expect(
|
||||
interpolatedSyncedLyricsPosition(
|
||||
anchorPosition: const Duration(seconds: 10),
|
||||
elapsedSinceAnchor: const Duration(milliseconds: 250),
|
||||
isPlaying: true,
|
||||
),
|
||||
const Duration(milliseconds: 10250),
|
||||
);
|
||||
expect(
|
||||
interpolatedSyncedLyricsPosition(
|
||||
anchorPosition: const Duration(seconds: 10),
|
||||
elapsedSinceAnchor: const Duration(milliseconds: 250),
|
||||
isPlaying: false,
|
||||
),
|
||||
const Duration(seconds: 10),
|
||||
);
|
||||
});
|
||||
|
||||
test('blends small clock corrections and applies seeks immediately', () {
|
||||
expect(
|
||||
reconcileSyncedLyricsPosition(
|
||||
predictedPosition: const Duration(milliseconds: 1000),
|
||||
reportedPosition: const Duration(milliseconds: 1100),
|
||||
),
|
||||
const Duration(milliseconds: 1025),
|
||||
);
|
||||
expect(
|
||||
reconcileSyncedLyricsPosition(
|
||||
predictedPosition: const Duration(seconds: 1),
|
||||
reportedPosition: const Duration(seconds: 5),
|
||||
),
|
||||
const Duration(seconds: 5),
|
||||
);
|
||||
});
|
||||
|
||||
test('calculates continuous progress inside a timed segment', () {
|
||||
const start = Duration(seconds: 2);
|
||||
const end = Duration(seconds: 3);
|
||||
|
||||
expect(
|
||||
syncedLyricSegmentProgress(
|
||||
position: const Duration(milliseconds: 1500),
|
||||
start: start,
|
||||
end: end,
|
||||
),
|
||||
0,
|
||||
);
|
||||
expect(
|
||||
syncedLyricSegmentProgress(
|
||||
position: const Duration(milliseconds: 2250),
|
||||
start: start,
|
||||
end: end,
|
||||
),
|
||||
0.25,
|
||||
);
|
||||
expect(
|
||||
syncedLyricSegmentProgress(
|
||||
position: const Duration(milliseconds: 3500),
|
||||
start: start,
|
||||
end: end,
|
||||
),
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
test('moves the reveal boundary from left to right', () {
|
||||
expect(
|
||||
syncedLyricsLeftToRightBoundary(left: 10, right: 110, progress: 0),
|
||||
10,
|
||||
);
|
||||
expect(
|
||||
syncedLyricsLeftToRightBoundary(left: 10, right: 110, progress: 0.5),
|
||||
60,
|
||||
);
|
||||
expect(
|
||||
syncedLyricsLeftToRightBoundary(left: 10, right: 110, progress: 1),
|
||||
110,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user