Improved work display, when available, ref #834
This commit is contained in:
@@ -40,18 +40,19 @@
|
|||||||
<div class="p-1">
|
<div class="p-1">
|
||||||
${cover}
|
${cover}
|
||||||
</div>
|
</div>
|
||||||
<div class="row align-items-center flex-fill overflow-hidden">
|
<div class="row align-items-center flex-fill">
|
||||||
<div class="col-12 col-md-6 col-lg-4">
|
<div class="col-12 col-md-6 col-lg-4">
|
||||||
<div class="p-2 overflow-hidden">
|
<div class="p-2">
|
||||||
<div class="d-block text-truncate">${name}</div>
|
<div class="d-block">${name}</div>
|
||||||
${<if-has-artists>}${artists class="d-block d-md-none text-truncate"}${</if-has-artists>}
|
${<if-has-artists>}${artists class="d-block d-md-none"}${</if-has-artists>}
|
||||||
|
${<if-has-work>}<div class="text-muted small ms-2">${work}</div>${</if-has-work>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-lg-4">
|
<div class="col-md-6 col-lg-4">
|
||||||
${<if-has-artists>}${artists-md class="d-none d-md-block text-truncate"}${</if-has-artists>}
|
${<if-has-artists>}${artists-md class="d-none d-md-block"}${</if-has-artists>}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4 text-truncate">
|
<div class="col-lg-4">
|
||||||
${<if-has-release>}${release class="d-none d-lg-inline text-truncate text-decoration-none link-success"}${</if-has-release>}
|
${<if-has-release>}${release class="d-none d-lg-inline text-decoration-none link-success"}${</if-has-release>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-2 d-none d-sm-block text-muted text-center Lms-tracks-entry-duration">
|
<div class="p-2 d-none d-sm-block text-muted text-center Lms-tracks-entry-duration">
|
||||||
|
|||||||
+8
-7
@@ -32,18 +32,19 @@
|
|||||||
<div class="p-1">
|
<div class="p-1">
|
||||||
${cover}
|
${cover}
|
||||||
</div>
|
</div>
|
||||||
<div class="row align-items-center flex-fill overflow-hidden">
|
<div class="row align-items-center flex-fill">
|
||||||
<div class="col-12 col-md-6 col-lg-4">
|
<div class="col-12 col-md-6 col-lg-4">
|
||||||
<div class="p-2 overflow-hidden">
|
<div class="p-2">
|
||||||
<div class="d-block text-truncate">${name}</div>
|
<div class="d-block">${name}</div>
|
||||||
${<if-has-artists>}${artists class="d-block d-md-none text-truncate"}${</if-has-artists>}
|
${<if-has-artists>}${artists class="d-block d-md-none"}${</if-has-artists>}
|
||||||
|
${<if-has-work>}<div class="text-muted small ms-2">${work}</div>${</if-has-work>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-lg-4">
|
<div class="col-md-6 col-lg-4">
|
||||||
${<if-has-artists>}${artists-md class="d-none d-md-block text-truncate"}${</if-has-artists>}
|
${<if-has-artists>}${artists-md class="d-none d-md-block"}${</if-has-artists>}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4 text-truncate">
|
<div class="col-lg-4">
|
||||||
${<if-has-release>}${release class="d-none d-lg-inline text-truncate text-decoration-none link-success"}${</if-has-release>}
|
${<if-has-release>}${release class="d-none d-lg-inline text-decoration-none link-success"}${</if-has-release>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-2 d-none d-sm-block text-muted text-center Lms-tracks-entry-duration">
|
<div class="p-2 d-none d-sm-block text-muted text-center Lms-tracks-entry-duration">
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ namespace lms::ui
|
|||||||
const std::string nativeResource{ _audioFileResource->getUrl(trackId) };
|
const std::string nativeResource{ _audioFileResource->getUrl(trackId) };
|
||||||
|
|
||||||
const auto artistDisplayInfo{ utils::computeArtistDisplayInfo(track, db::TrackArtistLinkType::Artist) };
|
const auto artistDisplayInfo{ utils::computeArtistDisplayInfo(track, db::TrackArtistLinkType::Artist) };
|
||||||
const std::string displayTitle{ utils::computeTrackDisplayTitle(track) };
|
const std::string displayTitle{ utils::computeTrackDisplayInfo(track).title };
|
||||||
|
|
||||||
oss
|
oss
|
||||||
<< "var params = {"
|
<< "var params = {"
|
||||||
|
|||||||
@@ -497,12 +497,17 @@ namespace lms::ui
|
|||||||
const auto track{ tracklistEntry->getTrack() };
|
const auto track{ tracklistEntry->getTrack() };
|
||||||
const db::TrackId trackId{ track->getId() };
|
const db::TrackId trackId{ track->getId() };
|
||||||
|
|
||||||
const std::string displayTitle{ utils::computeTrackDisplayTitle(track) };
|
const utils::TrackDisplayInfo displayInfo{ utils::computeTrackDisplayInfo(track) };
|
||||||
|
|
||||||
Template* entry{ _entriesContainer->addNew<Template>(Wt::WString::tr("Lms.PlayQueue.template.entry")) };
|
Template* entry{ _entriesContainer->addNew<Template>(Wt::WString::tr("Lms.PlayQueue.template.entry")) };
|
||||||
entry->addFunction("id", &Wt::WTemplate::Functions::id);
|
entry->addFunction("id", &Wt::WTemplate::Functions::id);
|
||||||
|
|
||||||
entry->bindString("name", Wt::WString::fromUTF8(displayTitle), Wt::TextFormat::Plain);
|
entry->bindString("name", Wt::WString::fromUTF8(displayInfo.title), Wt::TextFormat::Plain);
|
||||||
|
if (displayInfo.workName)
|
||||||
|
{
|
||||||
|
entry->setCondition("if-has-work", true);
|
||||||
|
entry->bindString("work", Wt::WString::fromUTF8(*displayInfo.workName), Wt::TextFormat::Plain);
|
||||||
|
}
|
||||||
|
|
||||||
const auto artists{ track->getArtistIds({ db::TrackArtistLinkType::Artist }) };
|
const auto artists{ track->getArtistIds({ db::TrackArtistLinkType::Artist }) };
|
||||||
if (!artists.empty())
|
if (!artists.empty())
|
||||||
@@ -541,7 +546,7 @@ namespace lms::ui
|
|||||||
entry->bindString("duration", utils::durationToString(track->getDuration()), Wt::TextFormat::Plain);
|
entry->bindString("duration", utils::durationToString(track->getDuration()), Wt::TextFormat::Plain);
|
||||||
|
|
||||||
Wt::WPushButton* playBtn{ entry->bindNew<Wt::WPushButton>("play-btn", Wt::WString::tr("Lms.template.play-btn"), Wt::TextFormat::XHTML) };
|
Wt::WPushButton* playBtn{ entry->bindNew<Wt::WPushButton>("play-btn", Wt::WString::tr("Lms.template.play-btn"), Wt::TextFormat::XHTML) };
|
||||||
playBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.play-item").arg(displayTitle));
|
playBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.play-item").arg(displayInfo.title));
|
||||||
playBtn->clicked().connect([this, entry] {
|
playBtn->clicked().connect([this, entry] {
|
||||||
const std::optional<std::size_t> pos{ _entriesContainer->getIndexOf(*entry) };
|
const std::optional<std::size_t> pos{ _entriesContainer->getIndexOf(*entry) };
|
||||||
if (pos)
|
if (pos)
|
||||||
@@ -549,7 +554,7 @@ namespace lms::ui
|
|||||||
});
|
});
|
||||||
|
|
||||||
Wt::WPushButton* delBtn{ entry->bindNew<Wt::WPushButton>("del-btn", Wt::WString::tr("Lms.template.delete-btn"), Wt::TextFormat::XHTML) };
|
Wt::WPushButton* delBtn{ entry->bindNew<Wt::WPushButton>("del-btn", Wt::WString::tr("Lms.template.delete-btn"), Wt::TextFormat::XHTML) };
|
||||||
delBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.delete-item").arg(displayTitle));
|
delBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.delete-item").arg(displayInfo.title));
|
||||||
delBtn->setToolTip(Wt::WString::tr("Lms.delete"));
|
delBtn->setToolTip(Wt::WString::tr("Lms.delete"));
|
||||||
delBtn->clicked().connect([this, tracklistEntryId, entry] {
|
delBtn->clicked().connect([this, tracklistEntryId, entry] {
|
||||||
// Remove the entry n both the widget tree and the playqueue
|
// Remove the entry n both the widget tree and the playqueue
|
||||||
|
|||||||
+14
-7
@@ -43,6 +43,7 @@
|
|||||||
#include "database/objects/Track.hpp"
|
#include "database/objects/Track.hpp"
|
||||||
#include "database/objects/TrackArtistLink.hpp"
|
#include "database/objects/TrackArtistLink.hpp"
|
||||||
#include "database/objects/TrackList.hpp"
|
#include "database/objects/TrackList.hpp"
|
||||||
|
#include "database/objects/Work.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
#include "ModalManager.hpp"
|
#include "ModalManager.hpp"
|
||||||
@@ -562,25 +563,31 @@ namespace lms::ui::utils
|
|||||||
LmsApp->doJavaScript("navigator.clipboard.writeText('" + core::stringUtils::jsEscape(text) + "').catch(function(){})");
|
LmsApp->doJavaScript("navigator.clipboard.writeText('" + core::stringUtils::jsEscape(text) + "').catch(function(){})");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string computeTrackDisplayTitle(const db::ObjectPtr<db::Track>& track)
|
TrackDisplayInfo computeTrackDisplayInfo(const db::ObjectPtr<db::Track>& track)
|
||||||
{
|
{
|
||||||
const auto movements{ track->getMovements() };
|
const auto movements{ track->getMovements() };
|
||||||
if (!movements.empty() && track->hasWork())
|
if (!movements.empty() && track->hasWork())
|
||||||
{
|
{
|
||||||
const db::Movement::pointer& movement{ movements.front() };
|
const db::Movement::pointer& movement{ movements.front() };
|
||||||
std::string result;
|
std::string title;
|
||||||
if (const auto n{ movement->getNumber() })
|
if (const auto n{ movement->getNumber() })
|
||||||
{
|
{
|
||||||
if (const std::string numeral{ core::stringUtils::toRomanNumeral(*n) }; !numeral.empty())
|
if (const std::string numeral{ core::stringUtils::toRomanNumeral(*n) }; !numeral.empty())
|
||||||
result += numeral + ". ";
|
title += numeral + ". ";
|
||||||
}
|
}
|
||||||
|
|
||||||
result += movement->getName();
|
title += movement->getName();
|
||||||
|
|
||||||
if (!result.empty())
|
if (!title.empty())
|
||||||
return result;
|
{
|
||||||
|
TrackDisplayInfo info{ .title = std::move(title), .workName = std::nullopt };
|
||||||
|
if (const auto works{ track->getWorks() }; !works.empty())
|
||||||
|
info.workName = std::string{ works.front()->getName() };
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string{ track->getName() };
|
return TrackDisplayInfo{ .title = std::string{ track->getName() }, .workName = std::nullopt };
|
||||||
}
|
}
|
||||||
} // namespace lms::ui::utils
|
} // namespace lms::ui::utils
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -104,6 +105,10 @@ namespace lms::ui::utils
|
|||||||
|
|
||||||
void copyToClipboard(std::string_view text);
|
void copyToClipboard(std::string_view text);
|
||||||
|
|
||||||
// Returns "i. MovementName" when track has work(s) + movement(s), otherwise track->getName().
|
struct TrackDisplayInfo
|
||||||
std::string computeTrackDisplayTitle(const db::ObjectPtr<db::Track>& track);
|
{
|
||||||
|
std::string title; // "i. MovementName" when track has work + movement, otherwise just the track's title
|
||||||
|
std::optional<std::string> workName; // only set when title comes from a movement
|
||||||
|
};
|
||||||
|
TrackDisplayInfo computeTrackDisplayInfo(const db::ObjectPtr<db::Track>& track);
|
||||||
} // namespace lms::ui::utils
|
} // namespace lms::ui::utils
|
||||||
|
|||||||
@@ -230,8 +230,13 @@ namespace lms::ui::TrackListHelpers
|
|||||||
auto entry{ std::make_unique<Template>(Wt::WString::tr("Lms.Explore.Tracks.template.entry")) };
|
auto entry{ std::make_unique<Template>(Wt::WString::tr("Lms.Explore.Tracks.template.entry")) };
|
||||||
auto* entryPtr{ entry.get() };
|
auto* entryPtr{ entry.get() };
|
||||||
|
|
||||||
const std::string displayTitle{ utils::computeTrackDisplayTitle(track) };
|
const utils::TrackDisplayInfo displayInfo{ utils::computeTrackDisplayInfo(track) };
|
||||||
entry->bindString("name", Wt::WString::fromUTF8(displayTitle), Wt::TextFormat::Plain);
|
entry->bindString("name", Wt::WString::fromUTF8(displayInfo.title), Wt::TextFormat::Plain);
|
||||||
|
if (displayInfo.workName)
|
||||||
|
{
|
||||||
|
entry->setCondition("if-has-work", true);
|
||||||
|
entry->bindString("work", Wt::WString::fromUTF8(*displayInfo.workName), Wt::TextFormat::Plain);
|
||||||
|
}
|
||||||
|
|
||||||
const db::Release::pointer release{ track->getRelease() };
|
const db::Release::pointer release{ track->getRelease() };
|
||||||
const db::TrackId trackId{ track->getId() };
|
const db::TrackId trackId{ track->getId() };
|
||||||
@@ -270,7 +275,7 @@ namespace lms::ui::TrackListHelpers
|
|||||||
entry->bindString("duration", utils::durationToString(track->getDuration()), Wt::TextFormat::Plain);
|
entry->bindString("duration", utils::durationToString(track->getDuration()), Wt::TextFormat::Plain);
|
||||||
|
|
||||||
Wt::WPushButton* playBtn{ entry->bindNew<Wt::WPushButton>("play-btn", Wt::WString::tr("Lms.template.play-btn"), Wt::TextFormat::XHTML) };
|
Wt::WPushButton* playBtn{ entry->bindNew<Wt::WPushButton>("play-btn", Wt::WString::tr("Lms.template.play-btn"), Wt::TextFormat::XHTML) };
|
||||||
playBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.play-item").arg(displayTitle));
|
playBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.play-item").arg(displayInfo.title));
|
||||||
playBtn->clicked().connect([trackId, &playQueueController] {
|
playBtn->clicked().connect([trackId, &playQueueController] {
|
||||||
db::TrackId trackIds[]{ trackId };
|
db::TrackId trackIds[]{ trackId };
|
||||||
playQueueController.processCommand(PlayQueueController::Command::Play, trackIds);
|
playQueueController.processCommand(PlayQueueController::Command::Play, trackIds);
|
||||||
@@ -302,7 +307,7 @@ namespace lms::ui::TrackListHelpers
|
|||||||
auto isStarred{ [=] { return core::Service<feedback::IFeedbackService>::get()->isStarred(LmsApp->getUserId(), trackId); } };
|
auto isStarred{ [=] { return core::Service<feedback::IFeedbackService>::get()->isStarred(LmsApp->getUserId(), trackId); } };
|
||||||
|
|
||||||
Wt::WPushButton* starBtn{ entry->bindNew<Wt::WPushButton>("star-btn", Wt::WString::tr(isStarred() ? "Lms.template.unstar-btn" : "Lms.template.star-btn"), Wt::TextFormat::XHTML) };
|
Wt::WPushButton* starBtn{ entry->bindNew<Wt::WPushButton>("star-btn", Wt::WString::tr(isStarred() ? "Lms.template.unstar-btn" : "Lms.template.star-btn"), Wt::TextFormat::XHTML) };
|
||||||
starBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.Explore.star-item").arg(displayTitle));
|
starBtn->setAttributeValue("aria-label", Wt::WString::tr("Lms.Explore.star-item").arg(displayInfo.title));
|
||||||
starBtn->setAttributeValue("aria-pressed", isStarred() ? "true" : "false");
|
starBtn->setAttributeValue("aria-pressed", isStarred() ? "true" : "false");
|
||||||
Wt::WPushButton* starMenuEntry{ entry->bindNew<Wt::WPushButton>("star", Wt::WString::tr(isStarred() ? "Lms.Explore.unstar" : "Lms.Explore.star")) };
|
Wt::WPushButton* starMenuEntry{ entry->bindNew<Wt::WPushButton>("star", Wt::WString::tr(isStarred() ? "Lms.Explore.unstar" : "Lms.Explore.star")) };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user