mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
AlbumView Added
This commit is contained in:
parent
b7a2b16bb6
commit
58148f3493
@ -1,9 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/components/Album/AlbumView.dart';
|
||||||
import 'package:spotube/components/Shared/PlaybuttonCard.dart';
|
import 'package:spotube/components/Shared/PlaybuttonCard.dart';
|
||||||
import 'package:spotube/helpers/artist-to-string.dart';
|
import 'package:spotube/helpers/artist-to-string.dart';
|
||||||
|
import 'package:spotube/helpers/simple-track-to-track.dart';
|
||||||
import 'package:spotube/provider/Playback.dart';
|
import 'package:spotube/provider/Playback.dart';
|
||||||
|
import 'package:spotube/provider/SpotifyDI.dart';
|
||||||
|
|
||||||
class AlbumCard extends StatelessWidget {
|
class AlbumCard extends StatelessWidget {
|
||||||
final Album album;
|
final Album album;
|
||||||
@ -12,6 +15,8 @@ class AlbumCard extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Playback playback = context.watch<Playback>();
|
Playback playback = context.watch<Playback>();
|
||||||
|
bool isPlaylistPlaying = playback.currentPlaylist != null &&
|
||||||
|
playback.currentPlaylist!.id == album.id;
|
||||||
|
|
||||||
return PlaybuttonCard(
|
return PlaybuttonCard(
|
||||||
imageUrl: album.images!.first.url!,
|
imageUrl: album.images!.first.url!,
|
||||||
@ -20,8 +25,29 @@ class AlbumCard extends StatelessWidget {
|
|||||||
title: album.name!,
|
title: album.name!,
|
||||||
description:
|
description:
|
||||||
"Alubm • ${artistsToString<ArtistSimple>(album.artists ?? [])}",
|
"Alubm • ${artistsToString<ArtistSimple>(album.artists ?? [])}",
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
onPlaybuttonPressed: () => {},
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return AlbumView(album);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
},
|
||||||
|
onPlaybuttonPressed: () async {
|
||||||
|
SpotifyApi spotify = context.read<SpotifyDI>().spotifyApi;
|
||||||
|
if (isPlaylistPlaying) return;
|
||||||
|
List<Track> tracks = (await spotify.albums.getTracks(album.id!).all())
|
||||||
|
.map((track) => simpleTrackToTrack(track, album))
|
||||||
|
.toList();
|
||||||
|
if (tracks.isEmpty) return;
|
||||||
|
|
||||||
|
playback.setCurrentPlaylist = CurrentPlaylist(
|
||||||
|
tracks: tracks,
|
||||||
|
id: album.id!,
|
||||||
|
name: album.name!,
|
||||||
|
thumbnail: album.images!.first.url!,
|
||||||
|
);
|
||||||
|
playback.setCurrentTrack = tracks.first;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
97
lib/components/Album/AlbumView.dart
Normal file
97
lib/components/Album/AlbumView.dart
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/components/Shared/PageWindowTitleBar.dart';
|
||||||
|
import 'package:spotube/components/Shared/TracksTableView.dart';
|
||||||
|
import 'package:spotube/helpers/simple-track-to-track.dart';
|
||||||
|
import 'package:spotube/provider/Playback.dart';
|
||||||
|
import 'package:spotube/provider/SpotifyDI.dart';
|
||||||
|
|
||||||
|
class AlbumView extends StatelessWidget {
|
||||||
|
final Album album;
|
||||||
|
const AlbumView(this.album, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
playPlaylist(Playback playback, List<Track> tracks, {Track? currentTrack}) {
|
||||||
|
currentTrack ??= tracks.first;
|
||||||
|
var isPlaylistPlaying = playback.currentPlaylist?.id == album.id;
|
||||||
|
if (!isPlaylistPlaying) {
|
||||||
|
playback.setCurrentPlaylist = CurrentPlaylist(
|
||||||
|
tracks: tracks,
|
||||||
|
id: album.id!,
|
||||||
|
name: album.name!,
|
||||||
|
thumbnail: album.images!.first.url!,
|
||||||
|
);
|
||||||
|
playback.setCurrentTrack = currentTrack;
|
||||||
|
} else if (isPlaylistPlaying &&
|
||||||
|
currentTrack.id != null &&
|
||||||
|
currentTrack.id != playback.currentTrack?.id) {
|
||||||
|
playback.setCurrentTrack = currentTrack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Playback playback = context.watch<Playback>();
|
||||||
|
|
||||||
|
var isPlaylistPlaying = playback.currentPlaylist?.id == album.id;
|
||||||
|
SpotifyApi spotify = context.watch<SpotifyDI>().spotifyApi;
|
||||||
|
return Scaffold(
|
||||||
|
body: FutureBuilder<Iterable<TrackSimple>>(
|
||||||
|
future: spotify.albums.getTracks(album.id!).all(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
List<Track> tracks = snapshot.data?.map((trackSmp) {
|
||||||
|
return simpleTrackToTrack(trackSmp, album);
|
||||||
|
}).toList() ??
|
||||||
|
[];
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
PageWindowTitleBar(
|
||||||
|
leading: Row(
|
||||||
|
children: [
|
||||||
|
// nav back
|
||||||
|
const BackButton(),
|
||||||
|
// heart playlist
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.favorite_outline_rounded),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
// play playlist
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
isPlaylistPlaying
|
||||||
|
? Icons.stop_rounded
|
||||||
|
: Icons.play_arrow_rounded,
|
||||||
|
),
|
||||||
|
onPressed: snapshot.hasData
|
||||||
|
? () => playPlaylist(playback, tracks)
|
||||||
|
: null,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Center(
|
||||||
|
child: Text(album.name!,
|
||||||
|
style: Theme.of(context).textTheme.headline4),
|
||||||
|
),
|
||||||
|
snapshot.hasError
|
||||||
|
? const Center(child: Text("Error occurred"))
|
||||||
|
: !snapshot.hasData
|
||||||
|
? const Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator.adaptive()),
|
||||||
|
)
|
||||||
|
: TracksTableView(
|
||||||
|
tracks,
|
||||||
|
onTrackPlayButtonPressed: (currentTrack) =>
|
||||||
|
playPlaylist(
|
||||||
|
playback,
|
||||||
|
tracks,
|
||||||
|
currentTrack: currentTrack,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
|
||||||
import 'package:spotube/components/Shared/PageWindowTitleBar.dart';
|
import 'package:spotube/components/Shared/PageWindowTitleBar.dart';
|
||||||
import 'package:spotube/helpers/zero-pad-num-str.dart';
|
import 'package:spotube/components/Shared/TracksTableView.dart';
|
||||||
import 'package:spotube/provider/Playback.dart';
|
import 'package:spotube/provider/Playback.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@ -17,7 +16,8 @@ class PlaylistView extends StatefulWidget {
|
|||||||
class _PlaylistViewState extends State<PlaylistView> {
|
class _PlaylistViewState extends State<PlaylistView> {
|
||||||
playPlaylist(Playback playback, List<Track> tracks, {Track? currentTrack}) {
|
playPlaylist(Playback playback, List<Track> tracks, {Track? currentTrack}) {
|
||||||
currentTrack ??= tracks.first;
|
currentTrack ??= tracks.first;
|
||||||
var isPlaylistPlaying = playback.currentPlaylist?.id == widget.playlist.id;
|
var isPlaylistPlaying = playback.currentPlaylist?.id != null &&
|
||||||
|
playback.currentPlaylist?.id == widget.playlist.id;
|
||||||
if (!isPlaylistPlaying) {
|
if (!isPlaylistPlaying) {
|
||||||
playback.setCurrentPlaylist = CurrentPlaylist(
|
playback.setCurrentPlaylist = CurrentPlaylist(
|
||||||
tracks: tracks,
|
tracks: tracks,
|
||||||
@ -33,111 +33,11 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TableRow> trackToTableRow(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(
|
|
||||||
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: () {
|
|
||||||
playPlaylist(playback, tracks, currentTrack: 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,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
(track.value.artists ?? [])
|
|
||||||
.map((e) => e.name)
|
|
||||||
.join(", "),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TableCell(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(
|
|
||||||
track.value.album?.name ?? "",
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TableCell(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(
|
|
||||||
duration,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Playback playback = context.watch<Playback>();
|
Playback playback = context.watch<Playback>();
|
||||||
var isPlaylistPlaying =
|
var isPlaylistPlaying = playback.currentPlaylist?.id != null &&
|
||||||
playback.currentPlaylist?.id == this.widget.playlist.id;
|
playback.currentPlaylist?.id == widget.playlist.id;
|
||||||
return Consumer<SpotifyDI>(builder: (_, data, __) {
|
return Consumer<SpotifyDI>(builder: (_, data, __) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: FutureBuilder<Iterable<Track>>(
|
body: FutureBuilder<Iterable<Track>>(
|
||||||
@ -150,8 +50,6 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
.then((tracks) => tracks.map((e) => e.track!)),
|
.then((tracks) => tracks.map((e) => e.track!)),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
List<Track> tracks = snapshot.data?.toList() ?? [];
|
List<Track> tracks = snapshot.data?.toList() ?? [];
|
||||||
TextStyle tableHeadStyle =
|
|
||||||
const TextStyle(fontWeight: FontWeight.bold, fontSize: 16);
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
PageWindowTitleBar(
|
PageWindowTitleBar(
|
||||||
@ -189,51 +87,13 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: CircularProgressIndicator.adaptive()),
|
child: CircularProgressIndicator.adaptive()),
|
||||||
)
|
)
|
||||||
: Expanded(
|
: TracksTableView(
|
||||||
child: Scrollbar(
|
tracks,
|
||||||
child: ListView(
|
onTrackPlayButtonPressed: (currentTrack) =>
|
||||||
children: [
|
playPlaylist(
|
||||||
SingleChildScrollView(
|
playback,
|
||||||
child: Table(
|
tracks,
|
||||||
columnWidths: const {
|
currentTrack: currentTrack,
|
||||||
0: FixedColumnWidth(40),
|
|
||||||
1: FlexColumnWidth(),
|
|
||||||
2: FlexColumnWidth(),
|
|
||||||
3: FixedColumnWidth(45),
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
TableRow(
|
|
||||||
children: [
|
|
||||||
TableCell(
|
|
||||||
child: Text(
|
|
||||||
"#",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: tableHeadStyle,
|
|
||||||
)),
|
|
||||||
TableCell(
|
|
||||||
child: Text(
|
|
||||||
"Title",
|
|
||||||
style: tableHeadStyle,
|
|
||||||
)),
|
|
||||||
TableCell(
|
|
||||||
child: Text(
|
|
||||||
"Album",
|
|
||||||
style: tableHeadStyle,
|
|
||||||
)),
|
|
||||||
TableCell(
|
|
||||||
child: Text(
|
|
||||||
"Time",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: tableHeadStyle,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
...trackToTableRow(playback, tracks),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
169
lib/components/Shared/TracksTableView.dart
Normal file
169
lib/components/Shared/TracksTableView.dart
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/helpers/zero-pad-num-str.dart';
|
||||||
|
import 'package:spotube/provider/Playback.dart';
|
||||||
|
|
||||||
|
class TracksTableView extends StatelessWidget {
|
||||||
|
final void Function(Track currentTrack)? onTrackPlayButtonPressed;
|
||||||
|
final List<Track> tracks;
|
||||||
|
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(
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
(track.value.artists ?? [])
|
||||||
|
.map((e) => e.name)
|
||||||
|
.join(", "),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TableCell(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
track.value.album?.name ?? "",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TableCell(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
duration,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(
|
||||||
|
children: [
|
||||||
|
TableCell(
|
||||||
|
child: Text(
|
||||||
|
"#",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: tableHeadStyle,
|
||||||
|
)),
|
||||||
|
TableCell(
|
||||||
|
child: Text(
|
||||||
|
"Title",
|
||||||
|
style: tableHeadStyle,
|
||||||
|
)),
|
||||||
|
TableCell(
|
||||||
|
child: Text(
|
||||||
|
"Album",
|
||||||
|
style: tableHeadStyle,
|
||||||
|
)),
|
||||||
|
TableCell(
|
||||||
|
child: Text(
|
||||||
|
"Time",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: tableHeadStyle,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
...trackToTableRow(context, playback, tracks),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
23
lib/helpers/simple-track-to-track.dart
Normal file
23
lib/helpers/simple-track-to-track.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:spotify/spotify.dart';
|
||||||
|
|
||||||
|
Track simpleTrackToTrack(TrackSimple trackSmp, Album album) {
|
||||||
|
Track track = Track();
|
||||||
|
track.name = trackSmp.name;
|
||||||
|
track.album = album;
|
||||||
|
track.artists = trackSmp.artists;
|
||||||
|
track.availableMarkets = trackSmp.availableMarkets;
|
||||||
|
track.discNumber = trackSmp.discNumber;
|
||||||
|
track.durationMs = trackSmp.durationMs;
|
||||||
|
track.explicit = trackSmp.explicit;
|
||||||
|
track.externalUrls = trackSmp.externalUrls;
|
||||||
|
track.href = trackSmp.href;
|
||||||
|
track.id = trackSmp.id;
|
||||||
|
track.isPlayable = trackSmp.isPlayable;
|
||||||
|
track.linkedFrom = trackSmp.linkedFrom;
|
||||||
|
track.name = trackSmp.name;
|
||||||
|
track.previewUrl = trackSmp.previewUrl;
|
||||||
|
track.trackNumber = trackSmp.trackNumber;
|
||||||
|
track.type = trackSmp.type;
|
||||||
|
track.uri = trackSmp.uri;
|
||||||
|
return track;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user