Skip to content

Commit

Permalink
Lazily load "appears on"
Browse files Browse the repository at this point in the history
  • Loading branch information
kraxarn committed Jan 2, 2024
1 parent 21654f7 commit eabfc9d
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 25 deletions.
31 changes: 31 additions & 0 deletions lib/include/lib/enums.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "lib/enum/albumgroup.hpp"
#include "lib/enum/mediatype.hpp"
#include "lib/enum/devicetype.hpp"
#include "lib/enum/playeraction.hpp"
Expand Down Expand Up @@ -287,5 +288,35 @@ namespace lib
}

//endregion

//region album_group

static void enum_to_string(const album_group album_group, std::string &str)
{
switch (album_group)
{
case album_group::album:
str = "album";
break;

case album_group::single:
str = "single";
break;

case album_group::compilation:
str = "compilation";
break;

case album_group::appears_on:
str = "appears_on";
break;

case album_group::none:
str = "";
break;
}
}

//endregion
};
}
2 changes: 1 addition & 1 deletion lib/include/lib/spotify/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ namespace lib
void related_artists(const lib::spt::artist &artist,
lib::callback<std::vector<lib::spt::artist>> &callback);

void albums(const spt::artist &artist,
void albums(const spt::artist &artist, const std::vector<album_group> &groups,
const paged_callback<spt::album> &callback) const;

//endregion
Expand Down
26 changes: 23 additions & 3 deletions lib/src/spotifyapi/artists.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "lib/uri.hpp"
#include "lib/spotify/api.hpp"

// Currently unavailable:
Expand Down Expand Up @@ -29,8 +30,27 @@ void lib::spt::api::related_artists(const lib::spt::artist &artist,
});
}

void lib::spt::api::albums(const spt::artist &artist, const paged_callback<spt::album> &callback) const
void lib::spt::api::albums(const spt::artist &artist, const std::vector<album_group> &groups,
const paged_callback<spt::album> &callback) const
{
const auto url = fmt::format("artists/{}/albums?limit=50&country=from_token", artist.id);
request.get_page<spt::album>(url, {}, callback);
uri uri(to_full_url(fmt::format("artists/{}/albums", artist.id)));

auto params = uri.get_search_params();
params.insert({"limit", "50"});

if (!groups.empty())
{
std::vector<std::string> groups_str;
groups_str.reserve(groups.size());

for (const auto &group: groups)
{
groups_str.push_back(enums<album_group>::to_string(group));
}

params.insert({"include_groups", strings::join(groups_str, ",")});
}

uri.set_search_params(params);
request.get_page<spt::album>(uri.get_url(), {}, callback);
}
107 changes: 87 additions & 20 deletions src/view/artist/albumslist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ Artist::AlbumsList::AlbumsList(lib::spt::api &spotify, lib::cache &cache,
QTreeWidget::connect(this, &QTreeWidget::itemEntered,
this, &Artist::AlbumsList::onItemEntered);

connect(this, &QTreeWidget::itemExpanded,
this, &AlbumsList::onItemExtended);

for (auto i = lib::album_group::album; i < lib::album_group::none;
i = static_cast<lib::album_group>(static_cast<int>(i) + 1))
{
Expand All @@ -49,8 +52,29 @@ auto Artist::AlbumsList::getAlbum(QTreeWidgetItem *item) -> lib::spt::album
void Artist::AlbumsList::loadAlbums(const lib::spt::page<lib::spt::album> &page)
{
setEnabled(false);
addAlbums(page.items);

if (page.has_next())
{
return;
}

setEnabled(true);

// Expand first group with items
for (const auto &group: groups)
{
if (group.second->childCount() > 0)
{
group.second->setExpanded(true);
break;
}
}
}

for (const auto &album: page.items)
void Artist::AlbumsList::addAlbums(const std::vector<lib::spt::album> &albums) const
{
for (const auto &album: albums)
{
const auto releaseDate = DateTime::parseIsoDate(album.release_date);
// Extra spacing is intentional so year doesn't overlap with scrollbar
Expand All @@ -60,10 +84,11 @@ void Artist::AlbumsList::loadAlbums(const lib::spt::page<lib::spt::album> &page)

auto *group = groups.at(album.album_group);
auto *item = new QTreeWidgetItem(group, {
albumName, year.isEmpty() ? QString() : year
albumName,
year.isEmpty() ? QString() : year
});

Http::getAlbumImage(album.image, httpClient, cache, [item, album](const QPixmap &image)
Http::getAlbumImage(album.image, httpClient, cache, [item](const QPixmap &image)
{
if (item != nullptr)
{
Expand All @@ -84,23 +109,6 @@ void Artist::AlbumsList::loadAlbums(const lib::spt::page<lib::spt::album> &page)

group->addChild(item);
}

if (page.has_next())
{
return;
}

setEnabled(true);

// Expand first group with items
for (const auto &group: groups)
{
if (group.second->childCount() > 0)
{
group.second->setExpanded(true);
break;
}
}
}

auto Artist::AlbumsList::groupToString(lib::album_group albumGroup) -> QString
Expand Down Expand Up @@ -185,3 +193,62 @@ void Artist::AlbumsList::onItemEntered(QTreeWidgetItem *item, int column)
const auto album = getAlbum(item);
tooltip.set(item, album, item->icon(0));
}

void Artist::AlbumsList::onItemExtended(const QTreeWidgetItem *item) const
{
constexpr auto pageSize = 50;
if (item == nullptr || item->childCount() != pageSize)
{
return;
}

if (item->text(0) != groupToString(lib::album_group::appears_on))
{
return;
}

const auto *view = Parent::findWidget<View>(parentWidget());
if (view == nullptr)
{
lib::log::debug("Parent isn't view ({})",
parent()->metaObject()->className());
return;
}

auto *group = groups.at(lib::album_group::appears_on);
group->setDisabled(true);

const auto &artist = view->getArtist();

spotify.albums(artist, {lib::album_group::appears_on},
[this, group](const lib::result<lib::spt::page<lib::spt::album>> &result) -> bool
{
if (!result.success())
{
StatusMessage::error(QString("Failed to load appears on albums: %1")
.arg(QString::fromStdString(result.message())));

return false;
}

const auto &page = result.value();
if (page.offset == 0)
{
group->setDisabled(true);
while (const auto *child = group->takeChild(0))
{
delete child;
}
}

addAlbums(page.items);

if (page.has_next())
{
return true;
}

group->setDisabled(false);
return false;
});
}
4 changes: 4 additions & 0 deletions src/view/artist/albumslist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ namespace Artist
{
class AlbumsList: public QTreeWidget
{
Q_OBJECT

public:
AlbumsList(lib::spt::api &spotify, lib::cache &cache,
const lib::http_client &httpClient, lib::settings &settings, QWidget *parent);

void loadAlbums(const lib::spt::page<lib::spt::album> &page);
void addAlbums(const std::vector<lib::spt::album> &albums) const;

private:
lib::spt::api &spotify;
Expand All @@ -35,5 +38,6 @@ namespace Artist
void onItemDoubleClicked(QTreeWidgetItem *item, int column);
void onContextMenu(const QPoint &pos);
void onItemEntered(QTreeWidgetItem *item, int column);
void onItemExtended(const QTreeWidgetItem *item) const;
};
}
27 changes: 26 additions & 1 deletion src/view/artist/view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ Artist::View::View(lib::spt::api &spotify, const std::string &artistId, lib::cac
});
}

auto Artist::View::getArtist() const -> const lib::spt::artist &
{
return artist;
}

void Artist::View::artistLoaded(const lib::spt::artist &loadedArtist)
{
artist = loadedArtist;
Expand Down Expand Up @@ -98,7 +103,13 @@ void Artist::View::artistLoaded(const lib::spt::artist &loadedArtist)
});

// Albums
spotify.albums(artist, [this](const lib::result<lib::spt::page<lib::spt::album>> &result) -> bool
const std::vector groups{
lib::album_group::album,
lib::album_group::single,
lib::album_group::compilation,
};

spotify.albums(artist, groups, [this](const lib::result<lib::spt::page<lib::spt::album>> &result) -> bool
{
if (!result.success())
{
Expand All @@ -112,6 +123,20 @@ void Artist::View::artistLoaded(const lib::spt::artist &loadedArtist)
return page.has_next();
});

spotify.albums(artist, {lib::album_group::appears_on},
[this](const lib::result<lib::spt::page<lib::spt::album>> &result) -> bool
{
if (!result.success())
{
lib::log::error("Failed to fetch appears on albums: {}", result.message());
return false;
}

const auto &page = result.value();
albumList->addAlbums(page.items);
return false;
});

// Related artists
spotify.related_artists(artist, [this](const std::vector<lib::spt::artist> &artists)
{
Expand Down
2 changes: 2 additions & 0 deletions src/view/artist/view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ namespace Artist
View(lib::spt::api &spotify, const std::string &artistId, lib::cache &cache,
const lib::http_client &httpClient, lib::settings &settings, QWidget *parent);

auto getArtist() const -> const lib::spt::artist &;

private:
void artistLoaded(const lib::spt::artist &loadedArtist);
void topTracksLoaded(const std::vector<lib::spt::track> &tracks);
Expand Down

0 comments on commit eabfc9d

Please sign in to comment.