Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support episodes when retrieving items from playlist #181

Open
hayribakici opened this issue Nov 29, 2023 · 1 comment
Open

Support episodes when retrieving items from playlist #181

hayribakici opened this issue Nov 29, 2023 · 1 comment

Comments

@hayribakici
Copy link
Collaborator

So far only tracks are retrieved from getTracksByPlaylistId. Spotify however also returns episodes.

@hayribakici
Copy link
Collaborator Author

hayribakici commented Nov 30, 2023

This kind of breaks the current Pages architecture. Currently, each Page can only hold one type with its dedicated parser. With multiple types, you need multiple parsers. So far, I am able to solve this issue with extending the BasePage and Page by another constructor and adding a new class MultiPage that allows multiple types:

  BasePage(this._paging, ParserFunction<T> pageItemParser,
      [Object? pageContainer]) {
    _items = _paging.itemsNative!.map(pageItemParser);
    _container = pageContainer;
  }


  BasePage.fromParserMap(
      this._paging, Map<String, ParserFunction<dynamic>> parserMap,
      [Object? pageContainer]) {
    _items = _paging.itemsNative!.map((item) {
      // so according to the spotify documentation, 
      // a json key `track` can either be a `Track` or `Episode` object.
      // Distinguishing between the two types is therefore only
      // possible by checking their `type` and therefore
      // run the according parser through that json object.
      var type = item["track"]["type"] as String; // <-- this is the line I don't like, needs further discussion
      if (parserMap.containsKey(type)) {
        return parserMap[type]!(item);
      }
      throw TypeError();
    });
    _container = pageContainer;
  }

...
class Page ... {
Page.fromParserMap(
      Paging<T> paging, Map<String, ParserFunction<dynamic>> parserMap,
      [Object? pageContainer])
      : super.fromParserMap(paging, parserMap);

}
...

/// Handles retrieval of a page with multiple types
class MultiPage extends SinglePages<dynamic, Page<dynamic>> with OffsetStrategy<Page<dynamic>> {
  final Map<String, ParserFunction<dynamic>> _pageMappers;

  MultiPage(SpotifyApiBase api, String path, this._pageMappers)
      : super(api, path, null, null);

  @override
  Future<Page<dynamic>> getPage(int limit, [int offset = 0]) async {
    var pathDelimiter = _path.contains('?') ? '&' : '?';
    var newPath = '$_path${pathDelimiter}limit=$limit&offset=$offset';

    var jsonString = await _api._get(newPath);
    var paging = Paging.fromJson(json.decode(jsonString));

    return Page.fromParserMap(paging, _pageMappers);
  }
}

And finally, distinguishing types in this new MultiPage class should be done with runtimeType.

var items = spotify.playlists.getItemsByPlaylistId('...');
var page = (await items.first()).items;
expect(page?.first?.runtimeType, Track);

I marked the line, where we could discuss this a bit more @rinukkusu .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant