mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-26 12:52:40 +02:00
fix(ui): align metadata and wrap track badges
This commit is contained in:
@@ -320,32 +320,25 @@ class _TrackItemWithStatus extends ConsumerWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: ClickableArtistName(
|
||||
artistName: track.artistName,
|
||||
artistId: track.artistId,
|
||||
coverUrl: track.coverUrl,
|
||||
extensionId: extensionId,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
TrackMetadataBadgesLine(
|
||||
primary: ClickableArtistName(
|
||||
artistName: track.artistName,
|
||||
artistId: track.artistId,
|
||||
coverUrl: track.coverUrl,
|
||||
extensionId: extensionId,
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(color: colorScheme.onSurfaceVariant),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
badges: [
|
||||
...buildQualityBadges(
|
||||
audioQuality: track.audioQuality,
|
||||
audioModes: track.audioModes,
|
||||
colorScheme: colorScheme,
|
||||
explicit: track.isExplicit,
|
||||
),
|
||||
if (isInLocalLibrary) ...[
|
||||
const SizedBox(width: 6),
|
||||
const InLibraryBadge(),
|
||||
],
|
||||
if (isInLocalLibrary) const InLibraryBadge(),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -522,7 +522,8 @@ extension _TrackMetadataCards on _TrackMetadataScreenState {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 4),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 100,
|
||||
|
||||
@@ -144,8 +144,44 @@ class DolbyLogoPainter extends CustomPainter {
|
||||
color != oldDelegate.color;
|
||||
}
|
||||
|
||||
/// Convenience builder: returns a list of quality badge widgets for a track.
|
||||
/// Pass the result into a Row using spread operator.
|
||||
/// Keeps artist text and optional track badges responsive on narrow rows.
|
||||
///
|
||||
/// A [Row] with a flexible artist still overflows when the badges themselves
|
||||
/// need more room than remains. [Wrap] moves whole badges to another run while
|
||||
/// keeping the artist constrained and ellipsized when it alone is too long.
|
||||
class TrackMetadataBadgesLine extends StatelessWidget {
|
||||
const TrackMetadataBadgesLine({
|
||||
super.key,
|
||||
required this.primary,
|
||||
this.badges = const [],
|
||||
});
|
||||
|
||||
final Widget primary;
|
||||
final List<Widget> badges;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (badges.isEmpty) return primary;
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) => Wrap(
|
||||
spacing: 6,
|
||||
runSpacing: 4,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: constraints.maxWidth),
|
||||
child: primary,
|
||||
),
|
||||
...badges,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the quality-related badge widgets for a track. Spacing and wrapping
|
||||
/// belong to [TrackMetadataBadgesLine] so the group stays responsive.
|
||||
List<Widget> buildQualityBadges({
|
||||
required String? audioQuality,
|
||||
required String? audioModes,
|
||||
@@ -154,17 +190,14 @@ List<Widget> buildQualityBadges({
|
||||
}) {
|
||||
final badges = <Widget>[];
|
||||
if (explicit) {
|
||||
badges.add(const SizedBox(width: 6));
|
||||
badges.add(ExplicitBadge(colorScheme: colorScheme));
|
||||
}
|
||||
if (audioQuality != null && audioQuality.isNotEmpty) {
|
||||
badges.add(const SizedBox(width: 6));
|
||||
badges.add(
|
||||
AudioQualityBadge(label: audioQuality, colorScheme: colorScheme),
|
||||
);
|
||||
}
|
||||
if (audioModes != null && audioModes.contains('DOLBY_ATMOS')) {
|
||||
badges.add(const SizedBox(width: 4));
|
||||
badges.add(DolbyAtmosBadge(colorScheme: colorScheme));
|
||||
}
|
||||
return badges;
|
||||
|
||||
@@ -76,36 +76,31 @@ class TrackListTile extends ConsumerWidget {
|
||||
isSelected: isSelected,
|
||||
leading: leading,
|
||||
title: track.name,
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: clickableArtist && !isSelectionMode
|
||||
? ClickableArtistName(
|
||||
artistName: track.artistName,
|
||||
artistId: track.artistId,
|
||||
coverUrl: track.coverUrl,
|
||||
extensionId: track.source,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
)
|
||||
: Text(
|
||||
track.artistName,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
),
|
||||
subtitle: TrackMetadataBadgesLine(
|
||||
primary: clickableArtist && !isSelectionMode
|
||||
? ClickableArtistName(
|
||||
artistName: track.artistName,
|
||||
artistId: track.artistId,
|
||||
coverUrl: track.coverUrl,
|
||||
extensionId: track.source,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
)
|
||||
: Text(
|
||||
track.artistName,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
badges: [
|
||||
...buildQualityBadges(
|
||||
audioQuality: track.audioQuality,
|
||||
audioModes: track.audioModes,
|
||||
colorScheme: colorScheme,
|
||||
explicit: track.isExplicit,
|
||||
),
|
||||
if (isInLocalLibrary || isInHistory) ...[
|
||||
const SizedBox(width: 6),
|
||||
const InLibraryBadge(),
|
||||
],
|
||||
if (isInLocalLibrary || isInHistory) const InLibraryBadge(),
|
||||
],
|
||||
),
|
||||
trailing: Row(
|
||||
|
||||
Reference in New Issue
Block a user