songs.dart 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import 'dart:convert';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/widgets.dart';
  4. import 'package:http/http.dart' as http;
  5. import '../types/song.dart';
  6. import '../utils/url.dart';
  7. import './spinner.dart';
  8. class Songs extends StatefulWidget {
  9. final String apiUrl;
  10. final String artist;
  11. final String album;
  12. final void Function(int) onSelect;
  13. Songs({
  14. @required this.apiUrl,
  15. @required this.artist, // can be an empty string
  16. @required this.album, // can be an empty string
  17. @required this.onSelect,
  18. });
  19. @override
  20. _SongsWidgetState createState() => _SongsWidgetState(
  21. apiUrl: this.apiUrl,
  22. artist: this.artist,
  23. album: this.album,
  24. onSelect: this.onSelect,
  25. );
  26. }
  27. Future<List<Song>> fetchSongs(String apiUrl, String artist) async {
  28. final response = await http.get(formattedUrl(apiUrl, '/songs', {
  29. 'artist': artist,
  30. }));
  31. if (response.statusCode != 200) {
  32. throw Exception('Failed to load songs');
  33. }
  34. List<Song> songs = [];
  35. var responseJson = jsonDecode(response.body)['songs'];
  36. for (var i = 0; i < responseJson.length; i++) {
  37. songs.add(Song.fromJson(responseJson[i]));
  38. }
  39. return songs;
  40. }
  41. class _SongsWidgetState extends State<Songs> {
  42. final String apiUrl;
  43. final String artist;
  44. final String album;
  45. Future<List<Song>> songs;
  46. final void Function(int) onSelect;
  47. _SongsWidgetState({
  48. @required this.apiUrl,
  49. @required this.artist,
  50. @required this.album,
  51. @required this.onSelect,
  52. });
  53. @override
  54. void initState() {
  55. super.initState();
  56. songs = fetchSongs(this.apiUrl, this.artist);
  57. }
  58. @override
  59. Widget build(BuildContext context) {
  60. return FutureBuilder<List<Song>>(
  61. future: songs,
  62. builder: (context, snapshot) {
  63. if (snapshot.hasData) {
  64. var filteredAlbums = this.album == null
  65. ? snapshot.data
  66. : snapshot.data.where((song) => song.album == this.album);
  67. return ListView(
  68. padding: EdgeInsets.only(left: 8, right: 8),
  69. children: filteredAlbums.map<Widget>((song) => Container(
  70. height: 40,
  71. color: Colors.white,
  72. child: Align(
  73. alignment: Alignment.centerLeft,
  74. child: TextButton(
  75. child: Text("${song.track} - ${song.title.length == 0 ? 'Untitled Track' : song.title}"),
  76. onPressed: () {
  77. onSelect(song.id);
  78. },
  79. style: TextButton.styleFrom(
  80. textStyle: TextStyle(fontSize: 18, fontStyle: FontStyle.normal),
  81. primary: Colors.black,
  82. ),
  83. ),
  84. ),
  85. )).toList(),
  86. );
  87. }
  88. if (snapshot.hasError) {
  89. return Text("${snapshot.error}");
  90. }
  91. return CenterSpinner();
  92. },
  93. );
  94. }
  95. }