Made a first split for Artist view. ref #235
This commit is contained in:
+13
-9
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<message id="Lms.Explore.Artist.template">
|
<message id="Lms.Explore.Artist.template">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<h3>${name}</h3>
|
<h2>${name}</h2>
|
||||||
${clusters class="mb-2"}
|
${clusters class="mb-2"}
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
${play-btn class="btn btn-primary"}
|
${play-btn class="btn btn-primary"}
|
||||||
@@ -20,17 +20,21 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${<if-has-release>}
|
${<if-has-releases>}
|
||||||
|
${<if-section-titles>}<h3>${tr:Lms.Explore.releases}</h3>${</if-section-titles>}
|
||||||
${releases class="mb-3"}
|
${releases class="mb-3"}
|
||||||
${</if-has-release>}
|
${</if-has-releases>}
|
||||||
${<if-has-non-release-track>}
|
${<if-has-appears-on-releases>}
|
||||||
|
${<if-section-titles>}<h3>${tr:Lms.Explore.Artist.appears-on}</h3>${</if-section-titles>}
|
||||||
|
${appears-on-releases class="mb-3"}
|
||||||
|
${</if-has-appears-on-releases>}
|
||||||
|
${<if-has-non-release-tracks>}
|
||||||
|
${<if-section-titles>}<h3>${tr:Lms.Explore.tracks}</h3>${</if-section-titles>}
|
||||||
${tracks class="mb-3"}
|
${tracks class="mb-3"}
|
||||||
${</if-has-non-release-track>}
|
${</if-has-non-release-tracks>}
|
||||||
${<if-has-similar-artists>}
|
${<if-has-similar-artists>}
|
||||||
<div>
|
<h3>${tr:Lms.Explore.Artist.similar-artists}</h3>
|
||||||
<h3>${tr:Lms.Explore.Artist.similar-artists}</h3>
|
${similar-artists class="d-grid gap-3"}
|
||||||
${similar-artists class="d-grid gap-3"}
|
|
||||||
</div>
|
|
||||||
${</if-has-similar-artists>}
|
${</if-has-similar-artists>}
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
<message id="Lms.Explore.various-artists">Various artists</message>
|
<message id="Lms.Explore.various-artists">Various artists</message>
|
||||||
|
|
||||||
<!--Explore:Artist-->
|
<!--Explore:Artist-->
|
||||||
|
<message id="Lms.Explore.Artist.appears-on">Appears on</message>
|
||||||
<message id="Lms.Explore.Artist.similar-artists">Similar artists</message>
|
<message id="Lms.Explore.Artist.similar-artists">Similar artists</message>
|
||||||
|
|
||||||
<!--Explore:Artists-->
|
<!--Explore:Artists-->
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
<message id="Lms.Explore.various-artists">Artistes divers</message>
|
<message id="Lms.Explore.various-artists">Artistes divers</message>
|
||||||
|
|
||||||
<!--Explore:Artist-->
|
<!--Explore:Artist-->
|
||||||
|
<message id="Lms.Explore.Artist.appears-on">Apparitions</message>
|
||||||
<message id="Lms.Explore.Artist.similar-artists">Artistes similaires</message>
|
<message id="Lms.Explore.Artist.similar-artists">Artistes similaires</message>
|
||||||
|
|
||||||
<!--Explore:Artists-->
|
<!--Explore:Artists-->
|
||||||
|
|||||||
@@ -136,6 +136,7 @@
|
|||||||
<message id="Lms.Explore.various-artists">Vari artisti</message>
|
<message id="Lms.Explore.various-artists">Vari artisti</message>
|
||||||
|
|
||||||
<!--Explore:Artist-->
|
<!--Explore:Artist-->
|
||||||
|
|
||||||
<message id="Lms.Explore.Artist.similar-artists">Artisti simili</message>
|
<message id="Lms.Explore.Artist.similar-artists">Artisti simili</message>
|
||||||
|
|
||||||
<!--Explore:Artists-->
|
<!--Explore:Artists-->
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
<message id="Lms.Explore.various-artists">群星</message>
|
<message id="Lms.Explore.various-artists">群星</message>
|
||||||
|
|
||||||
<!--Explore:Artist-->
|
<!--Explore:Artist-->
|
||||||
|
|
||||||
<message id="Lms.Explore.Artist.similar-artists">相似歌手</message>
|
<message id="Lms.Explore.Artist.similar-artists">相似歌手</message>
|
||||||
|
|
||||||
<!--Explore:Artists-->
|
<!--Explore:Artists-->
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@
|
|||||||
${cover}
|
${cover}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3>${name}</h3>
|
<h2>${name}</h2>
|
||||||
${<if-has-release-artists>}${artists}${</if-has-release-artists>}
|
${<if-has-release-artists>}${artists}${</if-has-release-artists>}
|
||||||
${<if-has-various-release-artists>}<div class="text-secondary">${tr:Lms.Explore.various-artists}</div>${</if-has-various-release-artists>}
|
${<if-has-various-release-artists>}<div class="text-secondary">${tr:Lms.Explore.various-artists}</div>${</if-has-various-release-artists>}
|
||||||
<div class="small text-muted">${<if-has-year>}${year}${<if-has-orig-year>} (${orig-year})${</if-has-orig-year>} · ${</if-has-year>}${duration}</div>
|
<div class="small text-muted">${<if-has-year>}${year}${<if-has-orig-year>} (${orig-year})${</if-has-orig-year>} · ${</if-has-year>}${duration}</div>
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ createQuery(Session& session, const Release::FindParameters& params)
|
|||||||
|
|
||||||
if (params.sortMethod == ReleaseSortMethod::LastWritten
|
if (params.sortMethod == ReleaseSortMethod::LastWritten
|
||||||
|| params.writtenAfter.isValid()
|
|| params.writtenAfter.isValid()
|
||||||
|| params.dateRange)
|
|| params.dateRange
|
||||||
|
|| params.artist.isValid())
|
||||||
{
|
{
|
||||||
query.join("track t ON t.release_id = r.id");
|
query.join("track t ON t.release_id = r.id");
|
||||||
}
|
}
|
||||||
@@ -66,6 +67,55 @@ createQuery(Session& session, const Release::FindParameters& params)
|
|||||||
.where("s_r.scrobbler = ?").bind(*params.scrobbler);
|
.where("s_r.scrobbler = ?").bind(*params.scrobbler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.artist.isValid())
|
||||||
|
{
|
||||||
|
query.join("artist a ON a.id = t_a_l.artist_id")
|
||||||
|
.join("track_artist_link t_a_l ON t_a_l.track_id = t.id")
|
||||||
|
.where("a.id = ?").bind(params.artist);
|
||||||
|
|
||||||
|
if (!params.trackArtistLinkTypes.empty())
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
bool first {true};
|
||||||
|
for (TrackArtistLinkType linkType : params.trackArtistLinkTypes)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
oss << " OR ";
|
||||||
|
oss << "t_a_l.type = ?";
|
||||||
|
query.bind(linkType);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
query.where(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!params.excludedTrackArtistLinkTypes.empty())
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "r.id NOT IN (SELECT DISTINCT r.id FROM release r"
|
||||||
|
" INNER JOIN artist a ON a.id = t_a_l.artist_id"
|
||||||
|
" INNER JOIN track_artist_link t_a_l ON t_a_l.track_id = t.id"
|
||||||
|
" INNER JOIN track t ON t.release_id = r.id"
|
||||||
|
" WHERE (a.id = ? AND (";
|
||||||
|
|
||||||
|
query.bind(params.artist);
|
||||||
|
|
||||||
|
bool first {true};
|
||||||
|
for (const TrackArtistLinkType linkType : params.excludedTrackArtistLinkTypes)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
oss << " OR ";
|
||||||
|
oss << "t_a_l.type = ?";
|
||||||
|
query.bind(linkType);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
oss << ")))";
|
||||||
|
query.where(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!params.clusters.empty())
|
if (!params.clusters.empty())
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
@@ -103,6 +153,9 @@ createQuery(Session& session, const Release::FindParameters& params)
|
|||||||
case ReleaseSortMethod::Date:
|
case ReleaseSortMethod::Date:
|
||||||
query.orderBy("t.date, r.name COLLATE NOCASE");
|
query.orderBy("t.date, r.name COLLATE NOCASE");
|
||||||
break;
|
break;
|
||||||
|
case ReleaseSortMethod::DateDesc:
|
||||||
|
query.orderBy("t.date DESC, r.name COLLATE NOCASE");
|
||||||
|
break;
|
||||||
case ReleaseSortMethod::StarredDateDesc:
|
case ReleaseSortMethod::StarredDateDesc:
|
||||||
assert(params.starringUser.isValid());
|
assert(params.starringUser.isValid());
|
||||||
query.orderBy("s_r.date_time DESC");
|
query.orderBy("s_r.date_time DESC");
|
||||||
|
|||||||
@@ -151,9 +151,9 @@ Session::prepareTables()
|
|||||||
_session.execute("CREATE INDEX IF NOT EXISTS tracklist_user_idx ON tracklist(user_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS tracklist_user_idx ON tracklist(user_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_features_track_idx ON track_features(track_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS track_features_track_idx ON track_features(track_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_artist_idx ON track_artist_link(artist_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_artist_idx ON track_artist_link(artist_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_name_idx ON track_artist_link(name)");
|
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_track_idx ON track_artist_link(track_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_track_idx ON track_artist_link(track_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_type_idx ON track_artist_link(type)");
|
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_type_idx ON track_artist_link(type)");
|
||||||
|
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_artist_type_idx ON track_artist_link(artist_id,type)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_bookmark_user_idx ON track_bookmark(user_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS track_bookmark_user_idx ON track_bookmark(user_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS track_bookmark_user_track_idx ON track_bookmark(user_id,track_id)");
|
_session.execute("CREATE INDEX IF NOT EXISTS track_bookmark_user_track_idx ON track_bookmark(user_id,track_id)");
|
||||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_scrobbler_idx ON listen(scrobbler)");
|
_session.execute("CREATE INDEX IF NOT EXISTS listen_scrobbler_idx ON listen(scrobbler)");
|
||||||
|
|||||||
@@ -25,11 +25,13 @@
|
|||||||
#include <Wt/WDateTime.h>
|
#include <Wt/WDateTime.h>
|
||||||
#include <Wt/Dbo/Dbo.h>
|
#include <Wt/Dbo/Dbo.h>
|
||||||
|
|
||||||
|
#include "services/database/ArtistId.hpp"
|
||||||
#include "services/database/ClusterId.hpp"
|
#include "services/database/ClusterId.hpp"
|
||||||
#include "services/database/Object.hpp"
|
#include "services/database/Object.hpp"
|
||||||
#include "services/database/ReleaseId.hpp"
|
#include "services/database/ReleaseId.hpp"
|
||||||
#include "services/database/Types.hpp"
|
#include "services/database/Types.hpp"
|
||||||
#include "services/database/UserId.hpp"
|
#include "services/database/UserId.hpp"
|
||||||
|
#include "utils/EnumSet.hpp"
|
||||||
#include "utils/UUID.hpp"
|
#include "utils/UUID.hpp"
|
||||||
|
|
||||||
namespace Database
|
namespace Database
|
||||||
@@ -54,8 +56,11 @@ class Release : public Object<Release, ReleaseId>
|
|||||||
Range range;
|
Range range;
|
||||||
Wt::WDateTime writtenAfter;
|
Wt::WDateTime writtenAfter;
|
||||||
std::optional<DateRange> dateRange;
|
std::optional<DateRange> dateRange;
|
||||||
UserId starringUser; // only releases starred by this user
|
UserId starringUser; // only releases starred by this user
|
||||||
std::optional<Scrobbler> scrobbler; // and for this scrobbler
|
std::optional<Scrobbler> scrobbler; // and for this scrobbler
|
||||||
|
ArtistId artist; // only releases that involved this user
|
||||||
|
EnumSet<TrackArtistLinkType> trackArtistLinkTypes; // and for these link types
|
||||||
|
EnumSet<TrackArtistLinkType> excludedTrackArtistLinkTypes; // but not for these link types
|
||||||
|
|
||||||
FindParameters& setClusters(const std::vector<ClusterId>& _clusters) { clusters = _clusters; return *this; }
|
FindParameters& setClusters(const std::vector<ClusterId>& _clusters) { clusters = _clusters; return *this; }
|
||||||
FindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
|
FindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
|
||||||
@@ -64,6 +69,13 @@ class Release : public Object<Release, ReleaseId>
|
|||||||
FindParameters& setWrittenAfter(const Wt::WDateTime& _after) {writtenAfter = _after; return *this; }
|
FindParameters& setWrittenAfter(const Wt::WDateTime& _after) {writtenAfter = _after; return *this; }
|
||||||
FindParameters& setDateRange(const std::optional<DateRange>& _dateRange) {dateRange = _dateRange; return *this; }
|
FindParameters& setDateRange(const std::optional<DateRange>& _dateRange) {dateRange = _dateRange; return *this; }
|
||||||
FindParameters& setStarringUser(UserId _user, Scrobbler _scrobbler) { starringUser = _user; scrobbler = _scrobbler; return *this; }
|
FindParameters& setStarringUser(UserId _user, Scrobbler _scrobbler) { starringUser = _user; scrobbler = _scrobbler; return *this; }
|
||||||
|
FindParameters& setArtist(ArtistId _artist, EnumSet<TrackArtistLinkType> _trackArtistLinkTypes = {}, EnumSet<TrackArtistLinkType> _excludedTrackArtistLinkTypes = {})
|
||||||
|
{
|
||||||
|
artist = _artist;
|
||||||
|
trackArtistLinkTypes = _trackArtistLinkTypes;
|
||||||
|
excludedTrackArtistLinkTypes = _excludedTrackArtistLinkTypes;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Release() = default;
|
Release() = default;
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ namespace Database
|
|||||||
void persist(Action& a)
|
void persist(Action& a)
|
||||||
{
|
{
|
||||||
Wt::Dbo::field(a, _type, "type");
|
Wt::Dbo::field(a, _type, "type");
|
||||||
Wt::Dbo::field(a, _type, "name");
|
|
||||||
|
|
||||||
Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade);
|
Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade);
|
||||||
Wt::Dbo::belongsTo(a, _artist, "artist", Wt::Dbo::OnDeleteCascade);
|
Wt::Dbo::belongsTo(a, _artist, "artist", Wt::Dbo::OnDeleteCascade);
|
||||||
@@ -62,7 +61,6 @@ namespace Database
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
TrackArtistLinkType _type;
|
TrackArtistLinkType _type;
|
||||||
std::string _name;
|
|
||||||
|
|
||||||
Wt::Dbo::ptr<Track> _track;
|
Wt::Dbo::ptr<Track> _track;
|
||||||
Wt::Dbo::ptr<Artist> _artist;
|
Wt::Dbo::ptr<Artist> _artist;
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ namespace Database
|
|||||||
None,
|
None,
|
||||||
Name,
|
Name,
|
||||||
Date,
|
Date,
|
||||||
|
DateDesc,
|
||||||
Random,
|
Random,
|
||||||
LastWritten,
|
LastWritten,
|
||||||
StarredDateDesc,
|
StarredDateDesc,
|
||||||
|
|||||||
@@ -396,4 +396,64 @@ TEST_F(DatabaseFixture, Release_writtenAfter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DatabaseFixture, Release_artist)
|
||||||
|
{
|
||||||
|
ScopedRelease release {session, "MyRelease"};
|
||||||
|
ScopedTrack track {session, "MyTrack"};
|
||||||
|
ScopedArtist artist {session, "MyArtist"};
|
||||||
|
ScopedArtist artist2 {session, "MyArtist2"};
|
||||||
|
{
|
||||||
|
auto transaction {session.createUniqueTransaction()};
|
||||||
|
track.get().modify()->setRelease(release.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
|
||||||
|
auto releases {Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist}))};
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist2.getId(), {TrackArtistLinkType::Artist}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction {session.createUniqueTransaction()};
|
||||||
|
TrackArtistLink::create(session, track.get(), artist.get(), TrackArtistLinkType::Artist);
|
||||||
|
|
||||||
|
auto releases {Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist}))};
|
||||||
|
ASSERT_EQ(releases.results.size(), 1);
|
||||||
|
EXPECT_EQ(releases.results.front(), release.getId());
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist, TrackArtistLinkType::Mixer}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 1);
|
||||||
|
EXPECT_EQ(releases.results.front(), release.getId());
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist2.getId(), {TrackArtistLinkType::Artist}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist2.getId()));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::ReleaseArtist, TrackArtistLinkType::Artist}));
|
||||||
|
ASSERT_EQ(releases.results.size(), 1);
|
||||||
|
EXPECT_EQ(releases.results.front(), release.getId());
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId()));
|
||||||
|
ASSERT_EQ(releases.results.size(), 1);
|
||||||
|
EXPECT_EQ(releases.results.front(), release.getId());
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Composer}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Composer, TrackArtistLinkType::Mixer}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {}, {TrackArtistLinkType::Artist}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
|
||||||
|
releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {}, {TrackArtistLinkType::Artist, TrackArtistLinkType::Composer}));
|
||||||
|
EXPECT_EQ(releases.results.size(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,11 +111,25 @@ Artist::refreshView()
|
|||||||
|
|
||||||
_artistId = *artistId;
|
_artistId = *artistId;
|
||||||
|
|
||||||
refreshReleases(artist);
|
std::size_t sectionCount{};
|
||||||
refreshNonReleaseTracks(artist);
|
|
||||||
|
LMS_LOG(UI, DEBUG) << "Refresh releases...";
|
||||||
|
if (refreshReleases())
|
||||||
|
sectionCount++;
|
||||||
|
LMS_LOG(UI, DEBUG) << "Refresh appears on releases...";
|
||||||
|
if (refreshAppearsOnReleases())
|
||||||
|
sectionCount++;
|
||||||
|
LMS_LOG(UI, DEBUG) << "Refresh non album tracks...";
|
||||||
|
if (refreshNonReleaseTracks(artist))
|
||||||
|
sectionCount++;
|
||||||
|
|
||||||
|
LMS_LOG(UI, DEBUG) << "Refresh links...";
|
||||||
refreshLinks(artist);
|
refreshLinks(artist);
|
||||||
refreshSimilarArtists(similarArtistIds);
|
refreshSimilarArtists(similarArtistIds);
|
||||||
|
|
||||||
|
if (sectionCount > 1)
|
||||||
|
setCondition("if-section-titles", true);
|
||||||
|
|
||||||
Wt::WContainerWidget* clusterContainers {bindNew<Wt::WContainerWidget>("clusters")};
|
Wt::WContainerWidget* clusterContainers {bindNew<Wt::WContainerWidget>("clusters")};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -177,35 +191,63 @@ Artist::refreshView()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
Artist::refreshReleases(const ObjectPtr<Database::Artist>& artist)
|
Artist::refreshReleases()
|
||||||
{
|
{
|
||||||
if (artist->getReleaseCount() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
setCondition("if-has-release", true);
|
|
||||||
_releaseContainer = bindNew<InfiniteScrollingContainer>("releases", Wt::WString::tr("Lms.Explore.Releases.template.container"));
|
_releaseContainer = bindNew<InfiniteScrollingContainer>("releases", Wt::WString::tr("Lms.Explore.Releases.template.container"));
|
||||||
_releaseContainer->onRequestElements.connect(this, [this]
|
_releaseContainer->onRequestElements.connect(this, [this]
|
||||||
{
|
{
|
||||||
addSomeReleases();
|
addSomeReleases(*_releaseContainer, {TrackArtistLinkType::ReleaseArtist}, {});
|
||||||
});
|
});
|
||||||
addSomeReleases();
|
|
||||||
|
const bool added {addSomeReleases(*_releaseContainer, {TrackArtistLinkType::ReleaseArtist}, {})};
|
||||||
|
setCondition("if-has-releases", added);
|
||||||
|
|
||||||
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
|
Artist::refreshAppearsOnReleases()
|
||||||
|
{
|
||||||
|
const EnumSet<TrackArtistLinkType> types
|
||||||
|
{
|
||||||
|
TrackArtistLinkType::Artist,
|
||||||
|
TrackArtistLinkType::Arranger,
|
||||||
|
TrackArtistLinkType::Composer,
|
||||||
|
TrackArtistLinkType::Conductor,
|
||||||
|
TrackArtistLinkType::Lyricist,
|
||||||
|
TrackArtistLinkType::Mixer,
|
||||||
|
TrackArtistLinkType::Performer,
|
||||||
|
TrackArtistLinkType::Producer,
|
||||||
|
TrackArtistLinkType::Remixer,
|
||||||
|
TrackArtistLinkType::Writer,
|
||||||
|
};
|
||||||
|
|
||||||
|
_appearsOnReleaseContainer = bindNew<InfiniteScrollingContainer>("appears-on-releases", Wt::WString::tr("Lms.Explore.Releases.template.container"));
|
||||||
|
_appearsOnReleaseContainer->onRequestElements.connect(this, [=]
|
||||||
|
{
|
||||||
|
addSomeReleases(*_appearsOnReleaseContainer, types, {TrackArtistLinkType::ReleaseArtist});
|
||||||
|
});
|
||||||
|
|
||||||
|
const bool added {addSomeReleases(*_appearsOnReleaseContainer, types, {TrackArtistLinkType::ReleaseArtist})};
|
||||||
|
setCondition("if-has-appears-on-releases", added);
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
Artist::refreshNonReleaseTracks(const ObjectPtr<Database::Artist>& artist)
|
Artist::refreshNonReleaseTracks(const ObjectPtr<Database::Artist>& artist)
|
||||||
{
|
{
|
||||||
if (!artist->hasNonReleaseTracks())
|
if (!artist->hasNonReleaseTracks())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
setCondition("if-has-non-release-track", true);
|
setCondition("if-has-non-release-tracks", true);
|
||||||
_trackContainer = bindNew<InfiniteScrollingContainer>("tracks");
|
_trackContainer = bindNew<InfiniteScrollingContainer>("tracks");
|
||||||
_trackContainer->onRequestElements.connect(this, [this]
|
_trackContainer->onRequestElements.connect(this, [this]
|
||||||
{
|
{
|
||||||
addSomeNonReleaseTracks();
|
addSomeNonReleaseTracks();
|
||||||
});
|
});
|
||||||
|
|
||||||
addSomeNonReleaseTracks();
|
return addSomeNonReleaseTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -238,35 +280,46 @@ Artist::refreshLinks(const Database::Artist::pointer& artist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
Artist::addSomeReleases()
|
Artist::addSomeReleases(InfiniteScrollingContainer& releaseContainer, EnumSet<Database::TrackArtistLinkType> linkTypes, EnumSet<Database::TrackArtistLinkType> excludedLinkTypes)
|
||||||
{
|
{
|
||||||
|
bool areArtistsAdded{};
|
||||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||||
|
|
||||||
const Database::Artist::pointer artist {Database::Artist::find(LmsApp->getDbSession(), _artistId)};
|
const Database::Artist::pointer artist {Database::Artist::find(LmsApp->getDbSession(), _artistId)};
|
||||||
if (!artist)
|
if (!artist)
|
||||||
return;
|
return areArtistsAdded;
|
||||||
|
|
||||||
const Range range {static_cast<std::size_t>(_releaseContainer->getCount()), _releasesBatchSize};
|
const Range range {static_cast<std::size_t>(releaseContainer.getCount()), _releasesBatchSize};
|
||||||
const auto releases {artist->getReleases(range, _filters->getClusterIds())};
|
|
||||||
|
|
||||||
|
Release::FindParameters params;
|
||||||
|
params.setClusters(_filters->getClusterIds());
|
||||||
|
params.setArtist(_artistId, linkTypes, excludedLinkTypes);
|
||||||
|
params.setRange(range);
|
||||||
|
params.setSortMethod(ReleaseSortMethod::DateDesc);
|
||||||
|
|
||||||
|
const auto releases {Release::find(LmsApp->getDbSession(), params)};
|
||||||
for (const ReleaseId releaseId : releases.results)
|
for (const ReleaseId releaseId : releases.results)
|
||||||
{
|
{
|
||||||
const Database::Release::pointer release {Database::Release::find(LmsApp->getDbSession(), releaseId)};
|
const Database::Release::pointer release {Database::Release::find(LmsApp->getDbSession(), releaseId)};
|
||||||
_releaseContainer->add(ReleaseListHelpers::createEntryForArtist(release, artist));
|
releaseContainer.add(ReleaseListHelpers::createEntryForArtist(release, artist));
|
||||||
|
areArtistsAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_releaseContainer->setHasMore(releases.moreResults);
|
releaseContainer.setHasMore(releases.moreResults);
|
||||||
|
|
||||||
|
return areArtistsAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
Artist::addSomeNonReleaseTracks()
|
Artist::addSomeNonReleaseTracks()
|
||||||
{
|
{
|
||||||
|
bool areTracksAdded{};
|
||||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||||
|
|
||||||
const Database::Artist::pointer artist {Database::Artist::find(LmsApp->getDbSession(), _artistId)};
|
const Database::Artist::pointer artist {Database::Artist::find(LmsApp->getDbSession(), _artistId)};
|
||||||
if (!artist)
|
if (!artist)
|
||||||
return;
|
return areTracksAdded;
|
||||||
|
|
||||||
const auto tracks {artist->getNonReleaseTracks(std::nullopt, Range {static_cast<std::size_t>(_trackContainer->getCount()), _tracksBatchSize})};
|
const auto tracks {artist->getNonReleaseTracks(std::nullopt, Range {static_cast<std::size_t>(_trackContainer->getCount()), _tracksBatchSize})};
|
||||||
bool moreResults {tracks.moreResults};
|
bool moreResults {tracks.moreResults};
|
||||||
@@ -280,9 +333,13 @@ Artist::addSomeNonReleaseTracks()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_trackContainer->add(TrackListHelpers::createEntry(track, tracksAction));
|
_trackContainer->add(TrackListHelpers::createEntry(track, tracksAction));
|
||||||
|
|
||||||
|
areTracksAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_trackContainer->setHasMore(moreResults);
|
_trackContainer->setHasMore(moreResults);
|
||||||
|
|
||||||
|
return areTracksAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "services/database/Object.hpp"
|
#include "services/database/Object.hpp"
|
||||||
|
#include "services/database/Types.hpp"
|
||||||
|
#include "utils/EnumSet.hpp"
|
||||||
#include "common/Template.hpp"
|
#include "common/Template.hpp"
|
||||||
|
|
||||||
#include "PlayQueueAction.hpp"
|
#include "PlayQueueAction.hpp"
|
||||||
@@ -46,19 +48,21 @@ namespace UserInterface
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void refreshView();
|
void refreshView();
|
||||||
void refreshReleases(const Database::ObjectPtr<Database::Artist>& artist);
|
bool refreshReleases();
|
||||||
void refreshNonReleaseTracks(const Database::ObjectPtr<Database::Artist>& artist);
|
bool refreshAppearsOnReleases();
|
||||||
|
bool refreshNonReleaseTracks(const Database::ObjectPtr<Database::Artist>& artist);
|
||||||
void refreshSimilarArtists(const std::vector<Database::ArtistId>& similarArtistsId);
|
void refreshSimilarArtists(const std::vector<Database::ArtistId>& similarArtistsId);
|
||||||
void refreshLinks(const Database::ObjectPtr<Database::Artist>& artist);
|
void refreshLinks(const Database::ObjectPtr<Database::Artist>& artist);
|
||||||
|
|
||||||
void addSomeReleases();
|
bool addSomeReleases(InfiniteScrollingContainer& container, EnumSet<Database::TrackArtistLinkType> linkTypes, EnumSet<Database::TrackArtistLinkType> excludedLinkTypes);
|
||||||
void addSomeNonReleaseTracks();
|
bool addSomeNonReleaseTracks();
|
||||||
static constexpr std::size_t _releasesBatchSize {6};
|
static constexpr std::size_t _releasesBatchSize {6};
|
||||||
static constexpr std::size_t _tracksBatchSize {6};
|
static constexpr std::size_t _tracksBatchSize {6};
|
||||||
static constexpr std::size_t _tracksMaxCount {160};
|
static constexpr std::size_t _tracksMaxCount {160};
|
||||||
|
|
||||||
Filters* _filters {};
|
Filters* _filters {};
|
||||||
InfiniteScrollingContainer* _releaseContainer {};
|
InfiniteScrollingContainer* _releaseContainer {};
|
||||||
|
InfiniteScrollingContainer* _appearsOnReleaseContainer {};
|
||||||
InfiniteScrollingContainer* _trackContainer {};
|
InfiniteScrollingContainer* _trackContainer {};
|
||||||
Database::ArtistId _artistId {};
|
Database::ArtistId _artistId {};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user