From 6608063d615a72a087c62f8b2b639fffba1e82c6 Mon Sep 17 00:00:00 2001 From: Daniel Thirion Date: Mon, 3 Mar 2025 23:14:37 +0100 Subject: [PATCH 1/5] Added initial implementation of inline remixers First implementation is a bit of a hardcode; working on making it work with all artist relations. Will then add a config flag or something for it to be user-toggleable. --- approot/release.xml | 3 +++ src/lms/ui/explore/ReleaseView.cpp | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/approot/release.xml b/approot/release.xml index 46b190f8..ac5f4009 100644 --- a/approot/release.xml +++ b/approot/release.xml @@ -123,6 +123,9 @@ + ${}
+ Remixer — ${remixers class="d-inline d-md-inline"} +
${
} diff --git a/src/lms/ui/explore/ReleaseView.cpp b/src/lms/ui/explore/ReleaseView.cpp index d6b6eff0..c4127b66 100644 --- a/src/lms/ui/explore/ReleaseView.cpp +++ b/src/lms/ui/explore/ReleaseView.cpp @@ -437,6 +437,13 @@ namespace lms::ui entry->bindWidget("artists-md", utils::createArtistDisplayNameWithAnchors(track->getArtistDisplayName(), artists)); } + const auto remixers{ track->getArtistIds({ TrackArtistLinkType::Remixer }) }; + if (!remixers.empty()) + { + entry->setCondition("if-has-remixers", true); + entry->bindWidget("remixers", utils::createArtistDisplayNameWithAnchors(track->getArtistDisplayName(), remixers)); + } + auto trackNumber{ track->getTrackNumber() }; if (trackNumber) { From 2e5c9e921880404705406172531d6f71f5945c65 Mon Sep 17 00:00:00 2001 From: Daniel Thirion Date: Tue, 4 Mar 2025 10:43:51 +0100 Subject: [PATCH 2/5] Implement inline artist credits For now, it's always shown. Soon, I will be implementing a setting to chose whether to show everything, remixers only, or nothing. --- approot/release.xml | 6 ++--- src/lms/ui/explore/ReleaseView.cpp | 43 ++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/approot/release.xml b/approot/release.xml index ac5f4009..91f5c97c 100644 --- a/approot/release.xml +++ b/approot/release.xml @@ -123,9 +123,9 @@ - ${}
- Remixer — ${remixers class="d-inline d-md-inline"} -
${
} + ${} + ${artist-links} + ${}
diff --git a/src/lms/ui/explore/ReleaseView.cpp b/src/lms/ui/explore/ReleaseView.cpp index c4127b66..4221b87e 100644 --- a/src/lms/ui/explore/ReleaseView.cpp +++ b/src/lms/ui/explore/ReleaseView.cpp @@ -437,11 +437,44 @@ namespace lms::ui entry->bindWidget("artists-md", utils::createArtistDisplayNameWithAnchors(track->getArtistDisplayName(), artists)); } - const auto remixers{ track->getArtistIds({ TrackArtistLinkType::Remixer }) }; - if (!remixers.empty()) - { - entry->setCondition("if-has-remixers", true); - entry->bindWidget("remixers", utils::createArtistDisplayNameWithAnchors(track->getArtistDisplayName(), remixers)); + { // Generate all artist link widgets + // TODO: add config to chose whether to only show Remixer or show All. + std::vector>> artistLinksList; + auto createTrackArtistLink = [&](TrackArtistLinkType linkType, const std::string& trkey) { + const auto artists{ track->getArtistIds({ linkType }) }; + const auto text = Wt::WString::trn(trkey, artists.size()).arg(artists.size()); + auto anchors{ utils::createArtistAnchorList(std::vector(std::cbegin(artists), std::cend(artists))) }; + if (!artists.empty()) + { + auto myPair = std::make_pair(text, std::move(anchors)); + artistLinksList.push_back(std::move(myPair)); + } + }; + createTrackArtistLink(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer"); + createTrackArtistLink(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer"); + createTrackArtistLink(TrackArtistLinkType::Performer, "Lms.Explore.Artists.linktype-performer"); + createTrackArtistLink(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer"); + createTrackArtistLink(TrackArtistLinkType::Conductor, "Lms.Explore.Artists.linktype-conductor"); + createTrackArtistLink(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist"); + createTrackArtistLink(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer"); + + if (!artistLinksList.empty()) + { + entry->setCondition("if-has-artist-links", true); + Wt::WContainerWidget* artistLinksContainer = entry->bindNew("artist-links"); + + for (auto& [role, artistWidget] : artistLinksList) + { + auto* currContainer = artistLinksContainer->addNew(); + currContainer->setStyleClass("overflow-hidden ms-5 pb-2 px-2 text-small d-flex"); + + auto* roleText = currContainer->addNew(role + Wt::WString::fromUTF8(" — ")); + roleText->setStyleClass("d-inline"); + + auto* newArtistWidget = currContainer->addWidget(std::move(artistWidget)); + newArtistWidget->setInline(true); + } + } } auto trackNumber{ track->getTrackNumber() }; From 1ef48880c38fb1cc3a22b6c1035292c89d3f7ea4 Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 8 Mar 2025 12:07:26 +0100 Subject: [PATCH 3/5] Some UI tweaks + display roles for performers --- approot/release.xml | 14 +++--- src/lms/ui/explore/ReleaseView.cpp | 60 +++++++++---------------- src/lms/ui/explore/TrackListHelpers.cpp | 30 ++++++++----- src/lms/ui/explore/TrackListHelpers.hpp | 5 +++ 4 files changed, 52 insertions(+), 57 deletions(-) diff --git a/approot/release.xml b/approot/release.xml index 91f5c97c..b103fc6d 100644 --- a/approot/release.xml +++ b/approot/release.xml @@ -94,13 +94,14 @@ ${}${track-number}${}
-
+
${name} ${}${artists class="d-block d-md-none"}${} + ${}${artist-links}${}
-
+
${}${artists-md class="d-none d-md-block"}${}
@@ -123,9 +124,12 @@
- ${} - ${artist-links} - ${} +
+ + +
+ ${role} — ${anchors class="ms-1"} +
diff --git a/src/lms/ui/explore/ReleaseView.cpp b/src/lms/ui/explore/ReleaseView.cpp index 4221b87e..f6f2a059 100644 --- a/src/lms/ui/explore/ReleaseView.cpp +++ b/src/lms/ui/explore/ReleaseView.cpp @@ -185,6 +185,24 @@ namespace lms::ui return core::stringUtils::readAs(wApp->internalPathNextPart("/release/")); } + + void fillTrackArtistLinks(Wt::WTemplate* trackEntry, const db::Track::pointer& track) + { + const std::map> artistsByRole{ TrackListHelpers::getArtistsByRole(track->getId()) }; + + if (artistsByRole.empty()) + return; + + trackEntry->setCondition("if-has-artist-links", true); + Wt::WContainerWidget* artistLinksContainer = trackEntry->bindNew("artist-links"); + + for (auto& [role, artists] : artistsByRole) + { + Wt::WTemplate* artistLinkEntry{ artistLinksContainer->addNew(Wt::WString::tr("Lms.Explore.Release.template.artist-links-entry")) }; + artistLinkEntry->bindString("role", role, Wt::TextFormat::Plain); + artistLinkEntry->bindWidget("anchors", utils::createArtistAnchorList(std::vector(std::cbegin(artists), std::cend(artists)))); + } + } } // namespace Release::Release(Filters& filters, PlayQueueController& playQueueController) @@ -415,7 +433,7 @@ namespace lms::ui const db::TrackId trackId{ track->getId() }; const auto discNumber{ track->getDiscNumber() }; - Wt::WContainerWidget* container; + Wt::WContainerWidget* container{}; if (useSubtitleContainers && discNumber) container = getOrAddDiscContainer(*discNumber, track->getDiscSubtitle()); else if (hasDiscSubtitle && !discNumber) @@ -437,45 +455,7 @@ namespace lms::ui entry->bindWidget("artists-md", utils::createArtistDisplayNameWithAnchors(track->getArtistDisplayName(), artists)); } - { // Generate all artist link widgets - // TODO: add config to chose whether to only show Remixer or show All. - std::vector>> artistLinksList; - auto createTrackArtistLink = [&](TrackArtistLinkType linkType, const std::string& trkey) { - const auto artists{ track->getArtistIds({ linkType }) }; - const auto text = Wt::WString::trn(trkey, artists.size()).arg(artists.size()); - auto anchors{ utils::createArtistAnchorList(std::vector(std::cbegin(artists), std::cend(artists))) }; - if (!artists.empty()) - { - auto myPair = std::make_pair(text, std::move(anchors)); - artistLinksList.push_back(std::move(myPair)); - } - }; - createTrackArtistLink(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer"); - createTrackArtistLink(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer"); - createTrackArtistLink(TrackArtistLinkType::Performer, "Lms.Explore.Artists.linktype-performer"); - createTrackArtistLink(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer"); - createTrackArtistLink(TrackArtistLinkType::Conductor, "Lms.Explore.Artists.linktype-conductor"); - createTrackArtistLink(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist"); - createTrackArtistLink(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer"); - - if (!artistLinksList.empty()) - { - entry->setCondition("if-has-artist-links", true); - Wt::WContainerWidget* artistLinksContainer = entry->bindNew("artist-links"); - - for (auto& [role, artistWidget] : artistLinksList) - { - auto* currContainer = artistLinksContainer->addNew(); - currContainer->setStyleClass("overflow-hidden ms-5 pb-2 px-2 text-small d-flex"); - - auto* roleText = currContainer->addNew(role + Wt::WString::fromUTF8(" — ")); - roleText->setStyleClass("d-inline"); - - auto* newArtistWidget = currContainer->addWidget(std::move(artistWidget)); - newArtistWidget->setInline(true); - } - } - } + fillTrackArtistLinks(entry, track); auto trackNumber{ track->getTrackNumber() }; if (trackNumber) diff --git a/src/lms/ui/explore/TrackListHelpers.cpp b/src/lms/ui/explore/TrackListHelpers.cpp index 572b4e80..3dada888 100644 --- a/src/lms/ui/explore/TrackListHelpers.cpp +++ b/src/lms/ui/explore/TrackListHelpers.cpp @@ -50,18 +50,8 @@ namespace lms::ui::TrackListHelpers { using namespace db; - void showTrackInfoModal(db::TrackId trackId, Filters& filters) + std::map> getArtistsByRole(db::TrackId trackId) { - auto transaction{ LmsApp->getDbSession().createReadTransaction() }; - - const db::Track::pointer track{ Track::find(LmsApp->getDbSession(), trackId) }; - if (!track) - return; - - auto trackInfo{ std::make_unique