mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
simplified the layout of TrackTableView
This commit is contained in:
parent
72ff732505
commit
8c3a62569a
@ -4,12 +4,10 @@ import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/components/Album/AlbumCard.dart';
|
||||
import 'package:spotube/components/Album/AlbumView.dart';
|
||||
import 'package:spotube/components/Artist/ArtistAlbumView.dart';
|
||||
import 'package:spotube/components/Artist/ArtistCard.dart';
|
||||
import 'package:spotube/components/Shared/LinkText.dart';
|
||||
import 'package:spotube/components/Shared/PageWindowTitleBar.dart';
|
||||
import 'package:spotube/helpers/artists-to-clickable-artists.dart';
|
||||
import 'package:spotube/components/Shared/TracksTableView.dart';
|
||||
import 'package:spotube/helpers/readable-number.dart';
|
||||
import 'package:spotube/helpers/zero-pad-num-str.dart';
|
||||
import 'package:spotube/provider/Playback.dart';
|
||||
@ -162,81 +160,49 @@ class _ArtistProfileState extends State<ArtistProfile> {
|
||||
"Top Tracks",
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(isPlaylistPlaying
|
||||
? Icons.stop_circle_rounded
|
||||
: Icons.play_circle_filled_rounded),
|
||||
color: Theme.of(context).primaryColor,
|
||||
onPressed: trackSnapshot.hasData
|
||||
? () =>
|
||||
playPlaylist(trackSnapshot.data!.toList())
|
||||
: null,
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).primaryColor,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(isPlaylistPlaying
|
||||
? Icons.stop_rounded
|
||||
: Icons.play_arrow_rounded),
|
||||
color: Colors.white,
|
||||
onPressed: trackSnapshot.hasData
|
||||
? () =>
|
||||
playPlaylist(trackSnapshot.data!.toList())
|
||||
: null,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
...trackSnapshot.data?.map((track) {
|
||||
...trackSnapshot.data
|
||||
?.toList()
|
||||
.asMap()
|
||||
.entries
|
||||
.map((track) {
|
||||
String duration =
|
||||
"${track.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
return Row(
|
||||
children: [
|
||||
if (track.album != null &&
|
||||
track.album!.images!.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(5)),
|
||||
child: CachedNetworkImage(
|
||||
placeholder: (context, url) {
|
||||
return Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Colors.green[300],
|
||||
);
|
||||
},
|
||||
imageUrl:
|
||||
track.album!.images!.last.url!,
|
||||
maxHeightDiskCache: 40,
|
||||
maxWidthDiskCache: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
track.name ?? "",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 17,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
artistsToClickableArtists(
|
||||
track.artists ?? []),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
LinkText(
|
||||
track.album!.name!,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
AlbumView(track.album!),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(duration)
|
||||
],
|
||||
"${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
String? thumbnailUrl = track.value.album != null &&
|
||||
track.value.album!.images!.isNotEmpty
|
||||
? track.value.album!.images!.last.url!
|
||||
: null;
|
||||
return TracksTableView.buildTrackTile(
|
||||
context,
|
||||
playback,
|
||||
duration: duration,
|
||||
track: track,
|
||||
thumbnailUrl: thumbnailUrl,
|
||||
onTrackPlayButtonPressed: (currentTrack) =>
|
||||
playPlaylist(
|
||||
trackSnapshot.data!.toList(),
|
||||
currentTrack: track.value,
|
||||
),
|
||||
);
|
||||
}).toList() ??
|
||||
}) ??
|
||||
[],
|
||||
]);
|
||||
},
|
||||
|
@ -14,154 +14,152 @@ class TracksTableView extends StatelessWidget {
|
||||
const TracksTableView(this.tracks, {Key? key, this.onTrackPlayButtonPressed})
|
||||
: super(key: key);
|
||||
|
||||
List<TableRow> trackToTableRow(
|
||||
BuildContext context, Playback playback, List<Track> tracks) {
|
||||
return tracks.asMap().entries.map((track) {
|
||||
String? thumbnailUrl = (track.value.album?.images?.isNotEmpty ?? false)
|
||||
? track.value.album?.images?.last.url
|
||||
: null;
|
||||
String duration =
|
||||
"${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
return (TableRow(
|
||||
children: [
|
||||
TableCell(
|
||||
child: Padding(
|
||||
static Widget buildTrackTile(
|
||||
BuildContext context,
|
||||
Playback playback, {
|
||||
required MapEntry<int, Track> track,
|
||||
required String duration,
|
||||
String? thumbnailUrl,
|
||||
final void Function(Track currentTrack)? onTrackPlayButtonPressed,
|
||||
}) {
|
||||
return Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
width: 25,
|
||||
child: Text(
|
||||
(track.key + 1).toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
if (thumbnailUrl != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
(track.key + 1).toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
)),
|
||||
TableCell(
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
playback.currentTrack?.id != null &&
|
||||
playback.currentTrack?.id == track.value.id
|
||||
? Icons.pause_circle_rounded
|
||||
: Icons.play_circle_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
onPressed: () => onTrackPlayButtonPressed?.call(
|
||||
track.value,
|
||||
),
|
||||
),
|
||||
if (thumbnailUrl != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||
child: CachedNetworkImage(
|
||||
placeholder: (context, url) {
|
||||
return Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Colors.green[300],
|
||||
);
|
||||
},
|
||||
imageUrl: thumbnailUrl,
|
||||
maxHeightDiskCache: 40,
|
||||
maxWidthDiskCache: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
track.value.name ?? "",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 17,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
artistsToClickableArtists(track.value.artists ?? []),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||
child: CachedNetworkImage(
|
||||
placeholder: (context, url) {
|
||||
return Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Colors.green[300],
|
||||
);
|
||||
},
|
||||
imageUrl: thumbnailUrl,
|
||||
maxHeightDiskCache: 40,
|
||||
maxWidthDiskCache: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: LinkText(
|
||||
track.value.album?.name ?? "",
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
playback.currentTrack?.id != null &&
|
||||
playback.currentTrack?.id == track.value.id
|
||||
? Icons.pause_circle_rounded
|
||||
: Icons.play_circle_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
onPressed: () => onTrackPlayButtonPressed?.call(
|
||||
track.value,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
track.value.name ?? "",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 17,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
artistsToClickableArtists(track.value.artists ?? []),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
LinkText(
|
||||
track.value.album!.name!,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => AlbumView(track.value.album!),
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
duration,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
));
|
||||
}).toList();
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(duration),
|
||||
const SizedBox(width: 10),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Playback playback = context.watch<Playback>();
|
||||
|
||||
TextStyle tableHeadStyle =
|
||||
const TextStyle(fontWeight: FontWeight.bold, fontSize: 16);
|
||||
return Expanded(
|
||||
child: Scrollbar(
|
||||
child: ListView(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
child: Table(
|
||||
columnWidths: const {
|
||||
0: FixedColumnWidth(40),
|
||||
1: FlexColumnWidth(),
|
||||
2: FlexColumnWidth(),
|
||||
3: FixedColumnWidth(45),
|
||||
},
|
||||
children: [
|
||||
TableRow(
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"#",
|
||||
textAlign: TextAlign.center,
|
||||
style: tableHeadStyle,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
TableCell(
|
||||
child: Text(
|
||||
"#",
|
||||
textAlign: TextAlign.center,
|
||||
style: tableHeadStyle,
|
||||
)),
|
||||
TableCell(
|
||||
child: Text(
|
||||
Text(
|
||||
"Title",
|
||||
style: tableHeadStyle,
|
||||
)),
|
||||
TableCell(
|
||||
child: Text(
|
||||
"Album",
|
||||
style: tableHeadStyle,
|
||||
)),
|
||||
TableCell(
|
||||
child: Text(
|
||||
"Time",
|
||||
textAlign: TextAlign.center,
|
||||
style: tableHeadStyle,
|
||||
)),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
...trackToTableRow(context, playback, tracks),
|
||||
],
|
||||
),
|
||||
),
|
||||
// used alignment of this table-head
|
||||
const SizedBox(width: 100),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Album",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: tableHeadStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text("Time", style: tableHeadStyle),
|
||||
const SizedBox(width: 10),
|
||||
],
|
||||
),
|
||||
...tracks.asMap().entries.map((track) {
|
||||
String? thumbnailUrl =
|
||||
(track.value.album?.images?.isNotEmpty ?? false)
|
||||
? track.value.album?.images?.last.url
|
||||
: null;
|
||||
String duration =
|
||||
"${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
return buildTrackTile(context, playback,
|
||||
track: track,
|
||||
duration: duration,
|
||||
thumbnailUrl: thumbnailUrl,
|
||||
onTrackPlayButtonPressed: onTrackPlayButtonPressed);
|
||||
}).toList()
|
||||
],
|
||||
),
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user