Giter VIP home page Giter VIP logo

Comments (13)

addreeh avatar addreeh commented on September 27, 2024 1

Sorry, I didnt have time to try those changes, but yes, can be clossed as completed. Thanks.

from spotify-dart.

rinukkusu avatar rinukkusu commented on September 27, 2024

Seems like you hit a quota and got rate limited. But maybe we need to think about some library level handling of such a situation.

What it means for you right now is, that you need to wait until you can make a request again. In the Developer Dashboard you should be able to see your current volume.

from spotify-dart.

addreeh avatar addreeh commented on September 27, 2024

image
image

Its probably that i hitted a quota because I tried a lot of things yesterday, but my question is if I deploy an app how can I handle these type of problems? Maybe creating another app and changing between them?

from spotify-dart.

hayribakici avatar hayribakici commented on September 27, 2024

@addreeh You could show the user a message, that the app is currently not usable and that he/she should try it again later. I suggest to check the code for unnecessary requests (sometimes they are done in some for-loops) and look for alternatives (e.g. instead of requesting all albums for each artist, you could collect each albumId for each artist and do a getSeveralAlbums request). That way you would reduce requests.

from spotify-dart.

addreeh avatar addreeh commented on September 27, 2024

Mmmm yes, is so probably that i am doing request that are unnecessary, I would glad if you could check my code and tell me if I can resume or delete something, if you don't have time close the issue, I understand that this is not the place for that. Thanks for the support.

Pasted Code
  _initApp() async {
    try {
      playlistSongs.clear();
      playlistArtists = [];
      playlistArtistsFull = [];
      playlistObject = await _getPlaylist(widget.playlistUrl);

      playlistDominantColor = await _getPlaylistDominantColor();
      _checkDominantColor();
      playlistDominantColorLight = _getLighterPlaylistDominantColor();
      playlistSongs = await _getPlaylistSongs();
      playlistDuration = _getPlaylistDuration();
      playlistArtists = await _getArtists();
      playlistArtistsFull = await _getFullArtist();

      playlistStatistics = _getArtistStatistics();

      setState(() {
        isLoading = false;
      });
    } catch (e) {
      print("Error al obtener canciones: $e");
      setState(() {
        isLoading = false;
      });
    }
  }

  String _extractPlaylistId(String spotifyLink) {
    RegExp regExp = RegExp(r'/playlist/([a-zA-Z0-9]+)');
    Match? match = regExp.firstMatch(spotifyLink);

    if (match != null && match.groupCount >= 1) {
      return match.group(1)!;
    } else {
      return "";
    }
  }

  Future<spotify.Playlist> _getPlaylist(String url) async {
    var playlist = await spotifyApi.playlists.get(_extractPlaylistId(url));
    return playlist;
  }

  void _checkDominantColor() {
    // Comparar los componentes de playlistDominantColor (rojo, verde y azul) con un umbral
    int umbral = 150;

    if (playlistDominantColor.red > umbral &&
        playlistDominantColor.green > umbral &&
        playlistDominantColor.blue > umbral) {
      bannerTextColor = Colors.black;
    } else {
      bannerTextColor = Colors.white;
    }
  }

  Future _getPlaylistDominantColor() async {
    try {
      var paletteGenerator = await PaletteGenerator.fromImageProvider(
        Image.network(playlistObject.images!.first.url!).image,
      );
      return paletteGenerator.dominantColor!.color;
    } catch (e) {
      return const Color(0xFF000000);
    }
  }

  _getLighterPlaylistDominantColor() {
    try {
      final hslColor = HSLColor.fromColor(playlistDominantColor);
      playlistDominantColorLight = hslColor
          .withLightness((hslColor.lightness).clamp(0.20, 0.51))
          .toColor();
      return playlistDominantColorLight;
    } catch (e) {
      return const Color(0xFF000000);
    }
  }

  Future<List<dynamic>> _getPlaylistSongs() async {
    List<dynamic> songs = [];

    int offset = 0;
    int limit = 100;
    int cont = 1;

    while (true) {
      try {
        var tracks = await spotifyApi.playlists
            .getTracksByPlaylistId(playlistObject.id)
            .getPage(limit, offset);
        if (tracks.items != null && tracks.items!.isNotEmpty) {
          try {
            for (var track in tracks.items!) {
              songs.add(track);
              cont++;
            }
            offset += limit;
          } catch (e) {
            cont++;
            offset = cont;
          }
        } else {
          break;
        }
      } catch (e) {
        print(e);
        showTopSnackBar(
          Overlay.of(context),
          const CustomSnackBar.error(
            message: "Something went wrong. Try it again later.",
          ),
        );
      }
    }

    return songs;
  }

  String _getPlaylistDuration() {
    num duration = 0;
    var uniqueArtists = <String>{};

    for (var song in playlistSongs) {
      duration += song.durationMs;

      for (var artist in song.artists) {
        if (artist.id != null && artist.name != null) {
          uniqueArtists.add(artist.id);
        }
      }
    }

    int seconds = (duration / 1000).round();
    int hours = seconds ~/ 3600;
    int minutes = (seconds % 3600) ~/ 60;

    String formattedDuration = hours > 0
        ? '$hours h ${minutes.toString().padLeft(2, '0')} min'
        : '$minutes min';

    return formattedDuration;
  }

  _getArtists() async {
    var artistIds =
        <String>{}; // Conjunto para almacenar IDs únicos de artistas
    var uniqueArtists =
        <spotify.Artist>[]; // Lista para almacenar artistas únicos

    for (var song in playlistSongs) {
      for (var artist in song.artists) {
        if (artist.id != null && artist.name != null) {
          if (!artistIds.contains(artist.id)) {
            // Si el ID del artista no está en el conjunto, agrega el artista
            artistIds.add(artist.id);
            uniqueArtists.add(artist);
          }
        }
      }
    }
    return uniqueArtists;
  }

  _getFullArtist() async {
    List<spotify.Artist> artists = [];
    for (var artist in playlistArtists) {
      try {
        var newArtist = await spotifyApi.artists.get(artist.id);
        artists.add(newArtist);
      } catch (e) {
        print(e);
        showTopSnackBar(
          Overlay.of(context),
          const CustomSnackBar.error(
            message: "Something went wrong. Try it again later.",
          ),
        );
      }
    }
    return artists;
  }

  List<ArtistResult> _getArtistStatistics() {
    List<ArtistResult> artistStatistics = [];

    for (var artist in playlistArtistsFull) {
      var artistTracks = <spotify.Track>[];

      for (var song in playlistSongs) {
        for (var songArtist in song.artists) {
          if (songArtist.id == artist.id) {
            artistTracks.add(song);
            break;
          }
        }
      }

      double percentage = double.parse(
          (artistTracks.length / playlistSongs.length * 100)
              .toStringAsFixed(2));

      ArtistResult result = ArtistResult(
        artist,
        artistTracks,
        artistTracks.length,
        percentage,
        // color,
      );
      artistStatistics.add(result);
    }

    artistStatistics.sort((a, b) => sortByPercentageAscending
        ? a.percentage.compareTo(b.percentage)
        : b.percentage.compareTo(a.percentage));

    return artistStatistics;
  }

from spotify-dart.

hayribakici avatar hayribakici commented on September 27, 2024
while (true) {
      try {
        var tracks = await spotifyApi.playlists
            .getTracksByPlaylistId(playlistObject.id)
            .getPage(limit, offset);
...
}
  1. So one thing, that looks suspicious is that you fetch all playlist items. If - let's say - a playlist has 300 tracks, but only - let's say - 15 are displayed, then it is indeed a waste of requests. As far as I understand your code, you want to display tracks from a playlist in a list (?). You could reduce requests by only GETting one Page at a time. This could be done with ListViews that allow to fetch more data once the end of the list is reached. Unfortunately I forgot the proper name of those lists, but with a quich search you would be able to find it.

_getFullArtist() async {
    List<spotify.Artist> artists = [];
    for (var artist in playlistArtists) {
      try {
        var newArtist = await spotifyApi.artists.get(artist.id);
        artists.add(newArtist);
      } catch (e) { ... }
    return artists;
  }
  1. You could use spotify.artists.list() here instead of requesting each artist individually. So in your case it would look like this:
_getFullArtist() async {
    // converting list of artists into list of artist id's
    var artistIds = playlistArtists.map((artist) => artist.id);
    // bulk retrieve artist information saving you the for-loop
    return await spotifyApi.artists.list(artistIds);
  }

Hope it helps :)

from spotify-dart.

hayribakici avatar hayribakici commented on September 27, 2024

Seems like you hit a quota and got rate limited. But maybe we need to think about some library level handling of such a situation.

@rinukkusu Maybe tracking the number of requests?

from spotify-dart.

addreeh avatar addreeh commented on September 27, 2024

My purpose is to do an app to track a playlist, it shows the percentage of songs that each artist has, because of that I have to get all the tracks and then I have to get each artist of each song, because of that i have to use a lot of loops that makes the app slow, but Im sure that if I would know all the methods of the library it will be faster jajaja

Pasted Code
// ignore_for_file: library_private_types_in_public_api, use_build_context_synchronously

import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:spotify/spotify.dart' as spotify;
import 'package:top_snackbar_flutter/custom_snack_bar.dart';
import 'package:top_snackbar_flutter/top_snack_bar.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:transformable_list_view/transformable_list_view.dart';
import 'package:expansion_tile_card/expansion_tile_card.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:palette_generator/palette_generator.dart';

final credentials = spotify.SpotifyApiCredentials(
    "", "");
var spotifyApi = spotify.SpotifyApi(credentials);

class ArtistResult {
  final spotify.Artist artist;
  final List<spotify.Track> tracks;
  final int total;
  final double percentage;
  // final Color color;

  ArtistResult(this.artist, this.tracks, this.total, this.percentage);
}

class Trackerfy extends StatefulWidget {
  final String playlistUrl;
  const Trackerfy(this.playlistUrl, {super.key});

  @override
  _TrackerfyState createState() => _TrackerfyState();
}

class _TrackerfyState extends State<Trackerfy> {
  bool showLoadingAnimation = true;

  var playlistObject;
  var playlistSongs = [];
  var playlistDuration = "";
  var playlistArtists = [];
  var playlistArtistsFull = [];
  bool isLoading = true;
  bool sortByPercentageAscending = false;
  final TextEditingController _searchController = TextEditingController();
  final bool _isSearching = false;
  var _filteredArtists = [];

  var playlistStatistics = [];

  Color playlistDominantColor = const Color(0xFF000000);
  Color playlistDominantColorLight = const Color(0xFF000000);
  Color bannerTextColor = Colors.white;

  @override
  void initState() {
    super.initState();

    _initApp();
    // Después de 5 segundos, oculta la animación de carga
    Future.delayed(const Duration(seconds: 5), () {
      setState(() {
        showLoadingAnimation = false;
      });
    });
  }

  _initApp() async {
    try {
      playlistSongs.clear();
      playlistArtists = [];
      playlistArtistsFull = [];
      playlistObject = await _getPlaylist(widget.playlistUrl);

      playlistDominantColor = await _getPlaylistDominantColor();
      _checkDominantColor();
      playlistDominantColorLight = _getLighterPlaylistDominantColor();
      playlistSongs = await _getPlaylistSongs();
      playlistDuration = _getPlaylistDuration();
      playlistArtists = await _getArtists();
      playlistArtistsFull = await _getFullArtist();

      playlistStatistics = _getArtistStatistics();

      setState(() {
        isLoading = false;
      });
    } catch (e) {
      print("Error al obtener canciones: $e");
      setState(() {
        isLoading = false;
      });
    }
  }

  String _extractPlaylistId(String spotifyLink) {
    RegExp regExp = RegExp(r'/playlist/([a-zA-Z0-9]+)');
    Match? match = regExp.firstMatch(spotifyLink);

    if (match != null && match.groupCount >= 1) {
      return match.group(1)!;
    } else {
      return "";
    }
  }

  Future<spotify.Playlist> _getPlaylist(String url) async {
    var playlist = await spotifyApi.playlists.get(_extractPlaylistId(url));
    return playlist;
  }

  void _checkDominantColor() {
    // Comparar los componentes de playlistDominantColor (rojo, verde y azul) con un umbral
    int umbral = 150;

    if (playlistDominantColor.red > umbral &&
        playlistDominantColor.green > umbral &&
        playlistDominantColor.blue > umbral) {
      bannerTextColor = Colors.black;
    } else {
      bannerTextColor = Colors.white;
    }
  }

  Future _getPlaylistDominantColor() async {
    try {
      var paletteGenerator = await PaletteGenerator.fromImageProvider(
        Image.network(playlistObject.images!.first.url!).image,
      );
      return paletteGenerator.dominantColor!.color;
    } catch (e) {
      return const Color(0xFF000000);
    }
  }

  _getLighterPlaylistDominantColor() {
    try {
      final hslColor = HSLColor.fromColor(playlistDominantColor);
      playlistDominantColorLight = hslColor
          .withLightness((hslColor.lightness).clamp(0.20, 0.51))
          .toColor();
      return playlistDominantColorLight;
    } catch (e) {
      return const Color(0xFF000000);
    }
  }

  Future<List<dynamic>> _getPlaylistSongs() async {
    List<dynamic> songs = [];

    int offset = 0;
    int limit = 100;
    int cont = 1;

    while (true) {
      try {
        var tracks = await spotifyApi.playlists
            .getTracksByPlaylistId(playlistObject.id)
            .getPage(limit, offset);
        if (tracks.items != null && tracks.items!.isNotEmpty) {
          try {
            for (var track in tracks.items!) {
              songs.add(track);
              cont++;
            }
            offset += limit;
          } catch (e) {
            cont++;
            offset = cont;
          }
        } else {
          break;
        }
      } catch (e) {
        print(e);
        showTopSnackBar(
          Overlay.of(context),
          const CustomSnackBar.error(
            message: "Something went wrong. Try it again later.",
          ),
        );
      }
    }

    return songs;
  }

  String _getPlaylistDuration() {
    num duration = 0;
    var uniqueArtists = <String>{};

    for (var song in playlistSongs) {
      duration += song.durationMs;

      for (var artist in song.artists) {
        if (artist.id != null && artist.name != null) {
          uniqueArtists.add(artist.id);
        }
      }
    }

    int seconds = (duration / 1000).round();
    int hours = seconds ~/ 3600;
    int minutes = (seconds % 3600) ~/ 60;

    String formattedDuration = hours > 0
        ? '$hours h ${minutes.toString().padLeft(2, '0')} min'
        : '$minutes min';

    return formattedDuration;
  }

  _getArtists() async {
    var artistIds =
        <String>{}; // Conjunto para almacenar IDs únicos de artistas
    var uniqueArtists =
        <spotify.Artist>[]; // Lista para almacenar artistas únicos

    for (var song in playlistSongs) {
      for (var artist in song.artists) {
        if (artist.id != null && artist.name != null) {
          if (!artistIds.contains(artist.id)) {
            // Si el ID del artista no está en el conjunto, agrega el artista
            artistIds.add(artist.id);
            uniqueArtists.add(artist);
          }
        }
      }
    }
    return uniqueArtists;
  }

  _getFullArtist() async {
    List<spotify.Artist> artists = [];
    for (var artist in playlistArtists) {
      try {
        var newArtist = await spotifyApi.artists.get(artist.id);
        artists.add(newArtist);
      } catch (e) {
        print(e);
        showTopSnackBar(
          Overlay.of(context),
          const CustomSnackBar.error(
            message: "Something went wrong. Try it again later.",
          ),
        );
      }
    }
    return artists;
  }

  List<ArtistResult> _getArtistStatistics() {
    List<ArtistResult> artistStatistics = [];

    for (var artist in playlistArtistsFull) {
      var artistTracks = <spotify.Track>[];

      for (var song in playlistSongs) {
        for (var songArtist in song.artists) {
          if (songArtist.id == artist.id) {
            artistTracks.add(song);
            break;
          }
        }
      }

      double percentage = double.parse(
          (artistTracks.length / playlistSongs.length * 100)
              .toStringAsFixed(2));

      ArtistResult result = ArtistResult(
        artist,
        artistTracks,
        artistTracks.length,
        percentage,
        // color,
      );
      artistStatistics.add(result);
    }

    artistStatistics.sort((a, b) => sortByPercentageAscending
        ? a.percentage.compareTo(b.percentage)
        : b.percentage.compareTo(a.percentage));

    return artistStatistics;
  }

  Matrix4 getTransformMatrix(TransformableListItem item) {
    const endScaleBound = 0.3;
    final animationProgress = item.visibleExtent / item.size.height;
    final paintTransform = Matrix4.identity();

    if (item.position != TransformableListItemPosition.middle) {
      final scale = endScaleBound + ((1 - endScaleBound) * animationProgress);

      paintTransform
        ..translate(item.size.width / 2)
        ..scale(scale)
        ..translate(-item.size.width / 2);
    }

    return paintTransform;
  }

  _launchURL(url) async {
    final Uri uri = Uri.parse(url);
    if (!await launchUrl(uri)) {
      throw Exception('Could not launch $uri');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF121212),
      body: ResponsiveBuilder(
        builder: (context, sizingInformation) {
          return Center(
            child: SizedBox(
              width: sizingInformation.isMobile
                  ? MediaQuery.of(context).size.width
                  : 450.0,
              child: showLoadingAnimation
                  ? Center(
                      child: LoadingAnimationWidget.horizontalRotatingDots(
                          color: Colors.white, size: 50),
                    )
                  : NestedScrollView(
                      headerSliverBuilder:
                          (BuildContext context, bool innerBoxIsScrolled) {
                        return <Widget>[
                          SliverAppBar(
                            shadowColor: playlistDominantColorLight,
                            automaticallyImplyLeading: false,
                            backgroundColor: playlistDominantColor,
                            title: Padding(
                              padding: const EdgeInsets.only(left: 5),
                              child: Text(
                                playlistObject.name ?? "Playlist",
                                style: TextStyle(
                                  fontFamily: "Circular Sp",
                                  fontSize: 18.0,
                                  fontWeight: FontWeight.bold,
                                  color: bannerTextColor,
                                ),
                              ),
                            ),
                            expandedHeight: 253,
                            floating: true,
                            pinned: true,
                            flexibleSpace: FlexibleSpaceBar(
                              background: Center(
                                child: Column(
                                  children: [
                                    SizedBox(
                                      height:
                                          sizingInformation.isMobile ? 85 : 65,
                                    ),
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.center,
                                      children: [
                                        const SizedBox(width: 20),
                                        Container(
                                          decoration: BoxDecoration(
                                            borderRadius:
                                                BorderRadius.circular(10.0),
                                            boxShadow: [
                                              BoxShadow(
                                                color:
                                                    playlistDominantColorLight,
                                                spreadRadius: 2,
                                                blurRadius: 5,
                                              ),
                                            ],
                                          ),
                                          child: ClipRRect(
                                            borderRadius:
                                                BorderRadius.circular(10.0),
                                            child: Image.network(
                                              playlistObject.images!.first.url!,
                                              width: 120,
                                              height: 120,
                                              fit: BoxFit.cover,
                                            ),
                                          ),
                                        ),
                                        const SizedBox(width: 20),
                                        Expanded(
                                          child: Column(
                                            crossAxisAlignment:
                                                CrossAxisAlignment.center,
                                            children: [
                                              Text(
                                                playlistObject.description!,
                                                style: TextStyle(
                                                  fontFamily: "Circular Sp",
                                                  fontSize: 12.0,
                                                  fontWeight: FontWeight.normal,
                                                  color: bannerTextColor,
                                                ),
                                                textAlign: TextAlign.center,
                                              ),
                                              const SizedBox(height: 10),
                                              Text(
                                                "Owner ➜${playlistObject.owner!.displayName!}",
                                                style: TextStyle(
                                                  fontFamily: "Circular Sp",
                                                  fontSize: 15.0,
                                                  fontWeight: FontWeight.normal,
                                                  color: bannerTextColor,
                                                ),
                                                textAlign: TextAlign.center,
                                              ),
                                              const SizedBox(height: 10),
                                              Text(
                                                playlistStatistics.isEmpty &&
                                                        playlistDuration == ""
                                                    ? "${playlistObject.tracks!.total} songs"
                                                    : playlistStatistics
                                                                .isEmpty &&
                                                            playlistDuration !=
                                                                ""
                                                        ? "${playlistObject.tracks!.total} songs ┃ $playlistDuration"
                                                        : "${playlistObject.tracks!.total} songs ┃ $playlistDuration ┃ ${playlistStatistics.length} artists",
                                                style: TextStyle(
                                                  fontFamily: "Circular Sp",
                                                  fontSize: 12.0,
                                                  fontWeight: FontWeight.normal,
                                                  color: bannerTextColor,
                                                ),
                                                textAlign: TextAlign.center,
                                              ),
                                            ],
                                          ),
                                        ),
                                        const SizedBox(width: 20),
                                      ],
                                    ),
                                    Row(
                                      children: [
                                        Expanded(
                                          child: Padding(
                                            padding: const EdgeInsets.fromLTRB(
                                                8, 10, 8, 0),
                                            child: TextField(
                                              cursorColor: bannerTextColor,
                                              controller: _searchController,
                                              style: TextStyle(
                                                fontFamily: "Circular Sp",
                                                color: bannerTextColor,
                                              ),
                                              decoration: InputDecoration(
                                                hintText: 'Search Artist ...',
                                                hintStyle: TextStyle(
                                                  fontFamily: "Circular Sp",
                                                  color: bannerTextColor,
                                                ),
                                                focusedBorder:
                                                    const OutlineInputBorder(
                                                  borderSide: BorderSide.none,
                                                ),
                                                enabledBorder:
                                                    const OutlineInputBorder(
                                                  borderSide: BorderSide.none,
                                                ),
                                                suffixIcon: Visibility(
                                                  visible: _searchController
                                                      .text.isNotEmpty,
                                                  child: InkWell(
                                                    onTap: () {
                                                      setState(() {
                                                        _searchController
                                                            .clear();
                                                        _filteredArtists = [];
                                                      });
                                                    },
                                                    focusNode: FocusNode(
                                                        skipTraversal: true),
                                                    child: Padding(
                                                      padding:
                                                          const EdgeInsets.all(
                                                              8.0),
                                                      child: Icon(
                                                        Icons.close,
                                                        color: bannerTextColor,
                                                        size: 20,
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                              ),
                                              onChanged: (value) {
                                                setState(() {
                                                  _filteredArtists =
                                                      playlistStatistics
                                                          .where((artist) => artist
                                                              .artist.name
                                                              .toLowerCase()
                                                              .contains(value
                                                                  .toLowerCase()))
                                                          .toList();
                                                });
                                              },
                                            ),
                                          ),
                                        ),
                                        Visibility(
                                          visible: !_searchController
                                                  .text.isNotEmpty &&
                                              !_isSearching &&
                                              !isLoading,
                                          child: IconButton(
                                            onPressed: () async {
                                              setState(() {
                                                sortByPercentageAscending =
                                                    !sortByPercentageAscending;
                                                isLoading = true;
                                                playlistStatistics =
                                                    _getArtistStatistics();
                                              });

                                              Future.delayed(
                                                  const Duration(seconds: 2),
                                                  () {
                                                setState(() {
                                                  isLoading = false;
                                                });
                                              });
                                            },
                                            icon: Icon(
                                              sortByPercentageAscending
                                                  ? Icons.arrow_upward
                                                  : Icons.arrow_downward,
                                              color: bannerTextColor,
                                            ),
                                          ),
                                        ),
                                        IconButton(
                                          onPressed: () {
                                            _launchURL(
                                                "https://open.spotify.com/playlist/${playlistObject.id}");
                                          },
                                          icon: Icon(
                                            Icons.link,
                                            color: bannerTextColor,
                                          ),
                                        ),
                                      ],
                                    )
                                  ],
                                ),
                              ),
                            ),
                          ),
                        ];
                      },
                      body: Column(
                        children: [
                          isLoading
                              ? Expanded(
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.center,
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      LoadingAnimationWidget.threeRotatingDots(
                                          color: Colors.white, size: 50),
                                      const SizedBox(
                                        height: 30,
                                      ),
                                      const SizedBox(
                                        width: 300,
                                        child: Text(
                                          "Please note that the waiting time will depend on the size of the playlist.",
                                          style: TextStyle(
                                            fontFamily: "Circular Sp",
                                            fontSize: 17.0,
                                            fontWeight: FontWeight.normal,
                                            color: Colors.white,
                                          ),
                                          textAlign: TextAlign.center,
                                        ),
                                      ),
                                    ],
                                  ),
                                )
                              : Expanded(
                                  child: TransformableListView.builder(
                                    padding: const EdgeInsets.fromLTRB(
                                        20, 10, 20, 20),
                                    getTransformMatrix: getTransformMatrix,
                                    itemBuilder: (context, index) {
                                      final GlobalKey<ExpansionTileCardState>
                                          cardKey = GlobalKey();
                                      final ArtistResult artist =
                                          _filteredArtists.isNotEmpty
                                              ? _filteredArtists[index]
                                              : playlistStatistics[index];
                                      return Padding(
                                        padding: const EdgeInsets.symmetric(
                                            vertical: 10.0),
                                        child: Container(
                                          decoration: BoxDecoration(
                                            borderRadius:
                                                BorderRadius.circular(10),
                                            boxShadow: [
                                              BoxShadow(
                                                color:
                                                    playlistDominantColorLight,
                                                spreadRadius: 2,
                                                blurRadius: 7.5,
                                              ),
                                            ],
                                          ),
                                          child: ExpansionTileCard(
                                            animateTrailing: true,
                                            trailing: const Icon(
                                              Icons.arrow_drop_down_rounded,
                                              color: Color(0xFFD2D2D2),
                                            ),
                                            baseColor: const Color(0xFF2a2a2a),
                                            // baseColor: playlistStatistics[index].color,
                                            expandedColor:
                                                const Color(0xFF383838),
                                            expandedTextColor:
                                                const Color(0xFFD2D2D2),
                                            shadowColor: playlistDominantColor,
                                            key: cardKey,
                                            leading: ClipOval(
                                              child: FadeInImage.assetNetwork(
                                                placeholder: "assets/load.png",
                                                image: artist
                                                    .artist.images![0].url
                                                    .toString(),
                                                width: 40.0,
                                                height: 40.0,
                                              ),
                                            ),

                                            // Dentro del itemBuilder del TransformableListView.builder
                                            title: Text(
                                              "${artist.artist.name} ➜ ${artist.percentage}% ",
                                              style: const TextStyle(
                                                fontFamily: "Circular Sp",
                                                fontSize: 17.0,
                                                fontWeight: FontWeight.normal,
                                                color: Color(0xFFD2D2D2),
                                              ),
                                            ),

                                            subtitle: Text(
                                              "${artist.total} songs ┃ Expand to see them.",
                                              style: const TextStyle(
                                                fontFamily: "Circular Sp",
                                                fontSize: 14.0,
                                                fontWeight: FontWeight.normal,
                                                color: Color(0xFFD2D2D2),
                                              ),
                                            ),
                                            children: <Widget>[
                                              Divider(
                                                thickness: 2.0,
                                                height: 1.0,
                                                color:
                                                    playlistDominantColorLight,
                                              ),
                                              Padding(
                                                padding:
                                                    const EdgeInsets.all(13),
                                                child: Container(
                                                  decoration: BoxDecoration(
                                                    border: Border.all(
                                                      color:
                                                          playlistDominantColorLight,
                                                      width: 0.5,
                                                    ),
                                                    borderRadius:
                                                        BorderRadius.circular(
                                                            10),
                                                    color:
                                                        const Color(0xFF454545),
                                                  ),
                                                  height: 150,
                                                  child: SingleChildScrollView(
                                                    padding:
                                                        const EdgeInsets.all(
                                                            10),
                                                    scrollDirection:
                                                        Axis.vertical,
                                                    child: Column(
                                                      crossAxisAlignment:
                                                          CrossAxisAlignment
                                                              .start,
                                                      children: <Widget>[
                                                        for (var song in artist
                                                            .tracks) ...[
                                                          Column(
                                                            crossAxisAlignment:
                                                                CrossAxisAlignment
                                                                    .start,
                                                            children: [
                                                              GestureDetector(
                                                                onTap:
                                                                    () async {
                                                                  _launchURL(
                                                                      "https://open.spotify.com/track/${song.id}");
                                                                },
                                                                child: Row(
                                                                  children: [
                                                                    const Icon(
                                                                      Icons
                                                                          .music_note_rounded,
                                                                      color: Color(
                                                                          0xFFD2D2D2),
                                                                      size:
                                                                          18.0,
                                                                    ),
                                                                    const SizedBox(
                                                                        width:
                                                                            5.0),
                                                                    Flexible(
                                                                      child:
                                                                          Text(
                                                                        "${song.name}",
                                                                        style:
                                                                            const TextStyle(
                                                                          fontFamily:
                                                                              "Circular Sp",
                                                                          fontSize:
                                                                              14.0,
                                                                          fontWeight:
                                                                              FontWeight.normal,
                                                                          color:
                                                                              Color(0xFFD2D2D2),
                                                                        ),
                                                                      ),
                                                                    ),
                                                                  ],
                                                                ),
                                                              ),
                                                              const SizedBox(
                                                                  height: 4.0),
                                                              Text(
                                                                "Artists: ${song.artists?.map((a) => a.name).join(', ')}",
                                                                style:
                                                                    const TextStyle(
                                                                  fontFamily:
                                                                      "Circular Sp",
                                                                  fontSize:
                                                                      14.0,
                                                                  fontWeight:
                                                                      FontWeight
                                                                          .normal,
                                                                  color: Colors
                                                                      .grey,
                                                                ),
                                                              ),
                                                              const SizedBox(
                                                                height: 4,
                                                              ),
                                                              Text(
                                                                "Album: ${song.album?.name}",
                                                                style:
                                                                    const TextStyle(
                                                                  fontFamily:
                                                                      "Circular Sp",
                                                                  fontSize:
                                                                      14.0,
                                                                  fontWeight:
                                                                      FontWeight
                                                                          .normal,
                                                                  color: Colors
                                                                      .grey,
                                                                ),
                                                              ),
                                                              const SizedBox(
                                                                  height: 8.0),
                                                            ],
                                                          ),
                                                        ],
                                                      ],
                                                    ),
                                                  ),
                                                ),
                                              ),
                                              ButtonBar(
                                                alignment: MainAxisAlignment
                                                    .spaceAround,
                                                buttonHeight: 52.0,
                                                buttonMinWidth: 90.0,
                                                children: <Widget>[
                                                  FloatingActionButton.extended(
                                                    backgroundColor:
                                                        playlistDominantColor,
                                                    onPressed: () {
                                                      _launchURL(
                                                          "https://open.spotify.com/artist/${playlistStatistics[index].artist.id}");
                                                    },
                                                    label: Text(
                                                      "Go to ${artist.artist.name}'s page",
                                                      style: TextStyle(
                                                          fontFamily:
                                                              "Circular Sp",
                                                          fontSize: 12.0,
                                                          fontWeight:
                                                              FontWeight.normal,
                                                          color:
                                                              bannerTextColor),
                                                    ),
                                                    icon: Icon(
                                                      Icons
                                                          .person_search_rounded,
                                                      color: bannerTextColor,
                                                    ),
                                                  ),
                                                ],
                                              ),
                                              const SizedBox(
                                                height: 5,
                                              ),
                                            ],
                                          ),
                                        ),
                                      );
                                    },
                                    itemCount: _filteredArtists.isNotEmpty
                                        ? _filteredArtists.length
                                        : playlistStatistics.length,
                                  ),
                                ),
                        ],
                      ),
                    ),
            ),
          );
        },
      ),
    );
  }
}

from spotify-dart.

hayribakici avatar hayribakici commented on September 27, 2024

@addreeh You can check out the wiki-page, where all implemented endpoints are listed.

from spotify-dart.

addreeh avatar addreeh commented on September 27, 2024

ok, thank you, finally can you tell me if the way i get all the tracks of the playlist is the correct?

from spotify-dart.

hayribakici avatar hayribakici commented on September 27, 2024

I tried your app out, and retrieving each track and having a statistic like that, is also the only way I would come up with. But I think, you could optimize some of your for loops, for example

...
int offset = 0;
int limit = 100;

while (true) {
try {
  var tracks = await spotifyApi.playlists
      .getTracksByPlaylistId(playlistObject?.id ?? '')
      .getPage(limit, offset);
  if (tracks.items != null && tracks.items!.isNotEmpty) {
    try {
      songs.addAll(tracks!.items); //<-- just use addAll instead of another for loop.
      offset += limit;
    } catch (e) {
      offset = songs.length;
    }

And you also could play around with the dart collection api. It has some methods that could make you remove some of your for loops.

from spotify-dart.

addreeh avatar addreeh commented on September 27, 2024

I will try it, thank you.

from spotify-dart.

hayribakici avatar hayribakici commented on September 27, 2024

@addreeh can this issue be closed?

from spotify-dart.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.