mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 21:29:36 +02:00
fix(lyrics): stagger highlight lift across graphemes
This commit is contained in:
1 parent
bf7dd5b1c4
commit
da5a0522ca
4 files changed
+121
-67
No files matched your search
@@ -2919,7 +2919,7 @@ void main() {
|
||||
for (final text in ['First second', 'Firsu secondu']) {
|
||||
final singingFirst = await pixelsAt(1100, text);
|
||||
final moves = mornye && text == 'First second';
|
||||
final firstEnded = await pixelsAt(moves ? 1600 : 1307, text);
|
||||
final firstEnded = await pixelsAt(moves ? 1800 : 1307, text);
|
||||
expect(firstEnded, isNot(orderedEquals(singingFirst)));
|
||||
if (moves) {
|
||||
expect(
|
||||
@@ -2928,11 +2928,11 @@ void main() {
|
||||
reason: 'Movement trails the finished color sweep',
|
||||
);
|
||||
}
|
||||
expect(await pixelsAt(1800, text), orderedEquals(firstEnded));
|
||||
expect(await pixelsAt(1820, text), orderedEquals(firstEnded));
|
||||
final singingLast = await pixelsAt(2150, text);
|
||||
final lastEnded = await pixelsAt(moves ? 2600 : 2497, text);
|
||||
final lastEnded = await pixelsAt(moves ? 3100 : 2497, text);
|
||||
expect(lastEnded, isNot(orderedEquals(singingLast)));
|
||||
expect(await pixelsAt(2900, text), orderedEquals(lastEnded));
|
||||
expect(await pixelsAt(3400, text), orderedEquals(lastEnded));
|
||||
expect(await pixelsAt(1100, text), orderedEquals(singingFirst));
|
||||
}
|
||||
final originalPixels = await pixelsAt(1100, 'First second');
|
||||
@@ -2994,7 +2994,9 @@ void main() {
|
||||
matching: find.byType(CustomPaint),
|
||||
);
|
||||
|
||||
Future<(double, double)> paintedHeights() async {
|
||||
Future<(double, double)> paintedHeights({
|
||||
bool firstWordLetters = false,
|
||||
}) async {
|
||||
final painter = tester.widget<CustomPaint>(paintFinder).painter!;
|
||||
final size = tester.getSize(paintFinder);
|
||||
return (await tester.runAsync(() async {
|
||||
@@ -3025,10 +3027,18 @@ void main() {
|
||||
return (top + bottom) / 2;
|
||||
}
|
||||
|
||||
final result = (
|
||||
centerFor(0, (image.width * 0.4).floor()),
|
||||
centerFor((image.width * 0.6).ceil(), image.width),
|
||||
);
|
||||
final result = firstWordLetters
|
||||
? (
|
||||
centerFor(0, (image.width * 0.1).floor()),
|
||||
centerFor(
|
||||
(image.width * 0.31).ceil(),
|
||||
(image.width * 0.39).floor(),
|
||||
),
|
||||
)
|
||||
: (
|
||||
centerFor(0, (image.width * 0.4).floor()),
|
||||
centerFor((image.width * 0.6).ceil(), image.width),
|
||||
);
|
||||
image.dispose();
|
||||
picture.dispose();
|
||||
return result;
|
||||
@@ -3048,25 +3058,36 @@ void main() {
|
||||
|
||||
final pending = await seek(800);
|
||||
final bounds = tester.getRect(paintFinder);
|
||||
final firstEnded = await seek(1600);
|
||||
await seek(1300);
|
||||
final letters = await paintedHeights(firstWordLetters: true);
|
||||
if (reducedMotion) {
|
||||
expect(letters.$1, letters.$2);
|
||||
} else {
|
||||
expect(
|
||||
letters.$1,
|
||||
lessThan(letters.$2),
|
||||
reason: 'Letters in one timed word must not rise as a block',
|
||||
);
|
||||
}
|
||||
final firstEnded = await seek(1900);
|
||||
expect(firstEnded.$2, pending.$2);
|
||||
if (reducedMotion) {
|
||||
expect(firstEnded, pending);
|
||||
} else {
|
||||
expect(pending.$1 - firstEnded.$1, inInclusiveRange(1, 2.5));
|
||||
}
|
||||
final held = await seek(4500);
|
||||
final held = await seek(5500);
|
||||
final settled = await seek(6000);
|
||||
expect(held.$1, firstEnded.$1);
|
||||
if (reducedMotion) {
|
||||
expect(held, pending);
|
||||
expect(settled, pending);
|
||||
} else {
|
||||
expect(settled.$2 - held.$2, greaterThan(1));
|
||||
expect(settled.$2 - held.$2, greaterThan(0));
|
||||
expect(pending.$2 - settled.$2, inInclusiveRange(1, 2.5));
|
||||
}
|
||||
expect(tester.getRect(paintFinder), bounds);
|
||||
expect(await seek(4500), held);
|
||||
expect(await seek(5500), held);
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(
|
||||
await paintedHeights(),
|
||||
|
||||
@@ -99,6 +99,31 @@ void main() {
|
||||
expect(liftAt(1200, end: 500), 0);
|
||||
});
|
||||
|
||||
test('graphemes rise in sweep order and converge after the word', () {
|
||||
double glyph(int time, double offset) => syncedLyricSegmentLift(
|
||||
position: Duration(milliseconds: time),
|
||||
start: const Duration(seconds: 1),
|
||||
end: const Duration(milliseconds: 1500),
|
||||
progressOffset: offset,
|
||||
);
|
||||
expect(glyph(1300, 0), greaterThan(glyph(1300, 0.33)));
|
||||
expect(glyph(1300, 0.33), greaterThan(glyph(1300, 0.66)));
|
||||
expect(glyph(1500, 0.75), lessThan(1));
|
||||
expect(glyph(2100, 0), 1);
|
||||
expect(glyph(2100, 0.75), 1);
|
||||
for (var time = 800; time < 2100; time += 16) {
|
||||
final change = glyph(time + 16, 0.75) - glyph(time, 0.75);
|
||||
expect(change, inInclusiveRange(0, 0.034));
|
||||
}
|
||||
final held = syncedLyricSegmentLift(
|
||||
position: const Duration(milliseconds: 5500),
|
||||
start: const Duration(seconds: 3),
|
||||
end: const Duration(seconds: 6),
|
||||
progressOffset: 0.75,
|
||||
);
|
||||
expect(held, greaterThan(1));
|
||||
});
|
||||
|
||||
test('interpolates position only while playback is advancing', () {
|
||||
expect(
|
||||
interpolatedSyncedLyricsPosition(
|
||||
|
||||
Reference in new issue
Block a user