fix(ui): align track play button hitboxes

This commit is contained in:
zarzet
2026-07-30 14:16:21 +07:00
parent 5228b0030b
commit 49d0bd6a99
2 changed files with 90 additions and 32 deletions
+21 -32
View File
@@ -42,27 +42,21 @@ class PreviewButton extends ConsumerWidget {
final mainItem = ref.watch(currentMediaItemProvider).value;
if (_isCurrentMainTrack(mainItem)) {
final isPlaying = ref.watch(playbackPlayingProvider);
return Transform.translate(
offset: const Offset(18, 0),
child: IconButton(
iconSize: size,
padding: EdgeInsets.zero,
alignment: Alignment.centerRight,
visualDensity: VisualDensity.compact,
constraints: const BoxConstraints(minWidth: 48, minHeight: 48),
icon: Icon(
isPlaying
? Icons.pause_circle_filled_rounded
: Icons.play_circle_fill_rounded,
color: colorScheme.primary,
),
tooltip: isPlaying
? context.l10n.previewStop
: context.l10n.previewPlay,
onPressed: () => ref
.read(musicPlayerControllerProvider)
.togglePlayPause(isPlaying),
return IconButton(
iconSize: size,
padding: EdgeInsets.zero,
constraints: const BoxConstraints(minWidth: 48, minHeight: 48),
icon: Icon(
isPlaying
? Icons.pause_circle_filled_rounded
: Icons.play_circle_fill_rounded,
color: colorScheme.primary,
),
tooltip: isPlaying
? context.l10n.previewStop
: context.l10n.previewPlay,
onPressed: () =>
ref.read(musicPlayerControllerProvider).togglePlayPause(isPlaying),
);
}
@@ -106,18 +100,13 @@ class PreviewButton extends ConsumerWidget {
break;
}
return Transform.translate(
offset: const Offset(18, 0),
child: IconButton(
iconSize: size,
padding: EdgeInsets.zero,
alignment: Alignment.centerRight,
visualDensity: VisualDensity.compact,
constraints: const BoxConstraints(minWidth: 48, minHeight: 48),
icon: icon,
tooltip: tooltip,
onPressed: () => _onPressed(context, ref),
),
return IconButton(
iconSize: size,
padding: EdgeInsets.zero,
constraints: const BoxConstraints(minWidth: 48, minHeight: 48),
icon: icon,
tooltip: tooltip,
onPressed: () => _onPressed(context, ref),
);
}
}
+69
View File
@@ -0,0 +1,69 @@
import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:spotiflac_android/l10n/l10n.dart';
import 'package:spotiflac_android/models/track.dart';
import 'package:spotiflac_android/providers/music_player_provider.dart';
import 'package:spotiflac_android/widgets/preview_button.dart';
void main() {
const track = Track(
id: 'track-1',
name: 'Track',
artistName: 'Artist',
albumName: 'Album',
previewUrl: 'https://example.com/preview.mp3',
duration: 180,
);
Future<void> pumpButton(WidgetTester tester, {MediaItem? currentItem}) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
currentMediaItemProvider.overrideWith(
(ref) => Stream.value(currentItem),
),
playbackPlayingProvider.overrideWith((ref) => false),
],
child: const MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold(body: PreviewButton(track: track)),
),
),
);
await tester.pump();
}
void expectCenteredHitbox(WidgetTester tester, IconData iconData) {
final button = find.byType(IconButton);
final icon = find.byIcon(iconData);
final hitbox = tester.getRect(button);
expect(hitbox.width, greaterThanOrEqualTo(48));
expect(hitbox.height, greaterThanOrEqualTo(48));
expect(tester.getCenter(icon), hitbox.center);
}
testWidgets('preview icon is centered inside its 48dp hitbox', (
tester,
) async {
await pumpButton(tester);
expectCenteredHitbox(tester, Icons.play_circle_outline_rounded);
});
testWidgets('current-track play icon uses the same centered hitbox', (
tester,
) async {
await pumpButton(
tester,
currentItem: const MediaItem(
id: 'track-1',
title: 'Track',
artist: 'Artist',
),
);
expectCenteredHitbox(tester, Icons.play_circle_fill_rounded);
});
}