Still converting to bootstrap 5. Fixed play queue
This commit is contained in:
+2
-2
@@ -7,9 +7,9 @@
|
|||||||
<h3>${name}</h3>
|
<h3>${name}</h3>
|
||||||
${clusters class="mb-2"}
|
${clusters class="mb-2"}
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
${play-btn class="btn btn-outline-primary me-2"}
|
${play-btn class="btn btn-primary me-2"}
|
||||||
<div class="dropdown d-inline-block">
|
<div class="dropdown d-inline-block">
|
||||||
${more-btn class="btn btn-outline-primary" data-bs-toggle="dropdown" aria-expanded="false"}
|
${more-btn class="btn btn-primary" data-bs-toggle="dropdown" aria-expanded="false"}
|
||||||
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
||||||
<li>${play-shuffled class="btn dropdown-item"}</li>
|
<li>${play-shuffled class="btn dropdown-item"}</li>
|
||||||
<li>${play-last class="btn dropdown-item"}</li>
|
<li>${play-last class="btn dropdown-item"}</li>
|
||||||
|
|||||||
+36
-18
@@ -2,38 +2,56 @@
|
|||||||
<messages xmlns:if="Wt.WTemplate.conditions">
|
<messages xmlns:if="Wt.WTemplate.conditions">
|
||||||
<!--FORMS message blocks-->
|
<!--FORMS message blocks-->
|
||||||
|
|
||||||
<message id="Lms.PlayQueue.template.clear-btn"><i class="fa fa-2x fa-times-circle"></i></message>
|
<message id="Lms.PlayQueue.template.clear-btn"><i class="fa fa-fw fa-times"></i></message>
|
||||||
<message id="Lms.PlayQueue.template.shuffle-btn"><i class="fa fa-2x fa-random"></i></message>
|
<message id="Lms.PlayQueue.template.shuffle-btn"><i class="fa fa-fw fa-random"></i></message>
|
||||||
<message id="Lms.PlayQueue.template.repeat-btn"><i class="fa fa-2x fa-repeat"></i></message>
|
<message id="Lms.PlayQueue.template.repeat-btn"><i class="fa fa-fw fa-repeat"></i></message>
|
||||||
<message id="Lms.PlayQueue.template.radio-btn"><i class="fa fa-2x fa-rss"></i></message>
|
<message id="Lms.PlayQueue.template.radio-btn"><i class="fa fa-fw fa-rss"></i></message>
|
||||||
|
|
||||||
<message id="Lms.PlayQueue.template">
|
<message id="Lms.PlayQueue.template">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
${clear-btn class="me-2"}${shuffle-btn class="me-2"}${repeat-btn class="me-2"}${radio-btn class="me-2"}
|
<div class="d-inline-block me-2" data-toggle="tooltip" title="${tr:Lms.PlayQueue.clear}">
|
||||||
|
${clear-btn class="btn btn-secondary"}
|
||||||
|
</div>
|
||||||
|
<div class="d-inline-block me-2" data-toggle="tooltip" title="${tr:Lms.PlayQueue.shuffle}">
|
||||||
|
${shuffle-btn class="btn btn-secondary"}
|
||||||
|
</div>
|
||||||
|
<div class="btn-group me-2">
|
||||||
|
${repeat-btn class="btn-check"}
|
||||||
|
<label class="btn btn-outline-info" data-toggle="tooltip" title="${tr:Lms.PlayQueue.repeat}" for="${id:repeat-btn}">${tr:Lms.PlayQueue.template.repeat-btn}</label>
|
||||||
|
${radio-btn class="btn-check"}
|
||||||
|
<label class="btn btn-outline-info" data-toggle="tooltip" title="${tr:Lms.PlayQueue.radio-mode}" for="${id:radio-btn}">${tr:Lms.PlayQueue.template.radio-btn}</label>
|
||||||
|
</div>
|
||||||
${nb-tracks}
|
${nb-tracks}
|
||||||
</div>
|
</div>
|
||||||
${entries}
|
${entries}
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message id="Lms.PlayQueue.template.play-btn"><i class="fa fa-2x fa-play-circle"></i></message>
|
<message id="Lms.PlayQueue.template.play-btn"><i class="fa fa-fw fa-play"></i></message>
|
||||||
<message id="Lms.PlayQueue.template.delete-btn"><i class="fa fa-2x fa-times-circle"></i></message>
|
<message id="Lms.PlayQueue.template.delete-btn"><i class="fa fa-fw fa-times"></i></message>
|
||||||
<message id="Lms.PlayQueue.template.more-btn"><i class="fa fa-2x fa-plus-circle"></i></message>
|
<message id="Lms.PlayQueue.template.more-btn"><i class="fa fa-fw fa-ellipsis-v"></i></message>
|
||||||
|
|
||||||
<message id="Lms.PlayQueue.template.entry">
|
<message id="Lms.PlayQueue.template.entry">
|
||||||
<div class="row Lms-vertical-align Lms-explore-entry-list Lms-playqueue-entry ${is-selected}">
|
<div class="d-flex align-items-center rounded Lms-bg-dark-hover">
|
||||||
<div class="col-3 col-sm-2 col-md-2">
|
<div class="p-1 Lms-cover-small">
|
||||||
${cover}
|
${cover}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-7 col-sm-8 col-md-8">
|
<div class="p-2 flex-fill">
|
||||||
${name}
|
<div>${name}</div>
|
||||||
${<if-has-artists-or-release>}
|
${<if-has-release>}${release class="text-decoration-none link-success"}${</if-has-release>}
|
||||||
${<if-has-release>}${release}${</if-has-release>}
|
|
||||||
${<if-has-artists>}${artists}${</if-has-artists>}
|
|
||||||
${</if-has-artists-or-release>}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2 col-sm-2 col-md-2">
|
<div class="p-2 d-none d-sm-block text-muted">
|
||||||
${duration}
|
${duration}
|
||||||
${play-btn class="me-2"}${del-btn class="me-2"}${more-btn}
|
</div>
|
||||||
|
<div class="p-2 d-flex">
|
||||||
|
${play-btn class="btn btn-sm btn-outline-secondary border-0"}
|
||||||
|
${del-btn class="btn btn-sm btn-outline-secondary border-0"}
|
||||||
|
<div class="dropdown d-none d-sm-block">
|
||||||
|
${more-btn data-bs-toggle="dropdown" aria-expanded="false" class="btn btn-sm btn-outline-secondary border-0"}
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
||||||
|
<li>${star class="btn dropdown-item"}</li>
|
||||||
|
<li>${download class="btn dropdown-item"}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
+2
-2
@@ -20,9 +20,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="mb-3 d-flex">
|
<div class="mb-3 d-flex">
|
||||||
${play-btn class="btn btn-outline-primary me-2"}
|
${play-btn class="btn btn-primary me-2"}
|
||||||
<div class="dropdown d-inline-block">
|
<div class="dropdown d-inline-block">
|
||||||
${more-btn class="btn btn-outline-primary" data-bs-toggle="dropdown" aria-expanded="false"}
|
${more-btn class="btn btn-primary" data-bs-toggle="dropdown" aria-expanded="false"}
|
||||||
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
||||||
<li>${play-shuffled class="btn dropdown-item"}</li>
|
<li>${play-shuffled class="btn dropdown-item"}</li>
|
||||||
<li>${play-last class="btn dropdown-item"}</li>
|
<li>${play-last class="btn dropdown-item"}</li>
|
||||||
|
|||||||
@@ -25,9 +25,9 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
${play-btn class="btn btn-outline-primary me-2"}
|
${play-btn class="btn btn-primary me-2"}
|
||||||
<div class="dropdown d-inline-block">
|
<div class="dropdown d-inline-block">
|
||||||
${more-btn data-bs-toggle="dropdown" aria-expanded="false" class="btn btn-outline-primary"}
|
${more-btn data-bs-toggle="dropdown" aria-expanded="false" class="btn btn-primary"}
|
||||||
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
||||||
<li>${play-last class="btn dropdown-item"}</li>
|
<li>${play-last class="btn dropdown-item"}</li>
|
||||||
<li>${play-shuffled class="btn dropdown-item"}</li>
|
<li>${play-shuffled class="btn dropdown-item"}</li>
|
||||||
|
|||||||
+2
-2
@@ -26,9 +26,9 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
${play-btn class="btn btn-outline-primary me-2"}
|
${play-btn class="btn btn-primary me-2"}
|
||||||
<div class="dropdown d-inline-block">
|
<div class="dropdown d-inline-block">
|
||||||
${more-btn data-bs-toggle="dropdown" aria-expanded="false" class="btn btn-outline-primary"}
|
${more-btn data-bs-toggle="dropdown" aria-expanded="false" class="btn btn-primary"}
|
||||||
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
<ul class="dropdown-menu" aria-labelledby="${id:more-btn}">
|
||||||
<li>${play-last class="btn dropdown-item"}</li>
|
<li>${play-last class="btn dropdown-item"}</li>
|
||||||
<li>${play-shuffled class="btn dropdown-item"}</li>
|
<li>${play-shuffled class="btn dropdown-item"}</li>
|
||||||
|
|||||||
+51
-79
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include "PlayQueue.hpp"
|
#include "PlayQueue.hpp"
|
||||||
|
|
||||||
#include <Wt/WPopupMenu.h>
|
#include <Wt/WCheckBox.h>
|
||||||
#include <Wt/WText.h>
|
#include <Wt/WPushButton.h>
|
||||||
|
|
||||||
#include "services/database/Cluster.hpp"
|
#include "services/database/Cluster.hpp"
|
||||||
#include "services/database/Release.hpp"
|
#include "services/database/Release.hpp"
|
||||||
@@ -45,25 +45,12 @@
|
|||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
PlayQueue::PlayQueue()
|
PlayQueue::PlayQueue()
|
||||||
: Wt::WTemplate(Wt::WString::tr("Lms.PlayQueue.template"))
|
: Template {Wt::WString::tr("Lms.PlayQueue.template")}
|
||||||
{
|
{
|
||||||
|
addFunction("id", &Wt::WTemplate::Functions::id);
|
||||||
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
{
|
|
||||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
|
||||||
_repeatAll = LmsApp->getUser()->isRepeatAllSet();
|
|
||||||
_radioMode = LmsApp->getUser()->isRadioSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto setToolTip = [](Wt::WWidget& widget, Wt::WString title)
|
|
||||||
{
|
|
||||||
widget.setAttributeValue("data-toggle", "tooltip");
|
|
||||||
widget.setAttributeValue("data-placement", "bottom");
|
|
||||||
widget.setAttributeValue("title", std::move(title));
|
|
||||||
};
|
|
||||||
|
|
||||||
Wt::WText* clearBtn = bindNew<Wt::WText>("clear-btn", Wt::WString::tr("Lms.PlayQueue.template.clear-btn"), Wt::TextFormat::XHTML);
|
Wt::WText* clearBtn = bindNew<Wt::WText>("clear-btn", Wt::WString::tr("Lms.PlayQueue.template.clear-btn"), Wt::TextFormat::XHTML);
|
||||||
setToolTip(*clearBtn, Wt::WString::tr("Lms.PlayQueue.clear"));
|
|
||||||
clearBtn->clicked().connect([=]
|
clearBtn->clicked().connect([=]
|
||||||
{
|
{
|
||||||
clearTracks();
|
clearTracks();
|
||||||
@@ -77,7 +64,6 @@ PlayQueue::PlayQueue()
|
|||||||
});
|
});
|
||||||
|
|
||||||
Wt::WText* shuffleBtn = bindNew<Wt::WText>("shuffle-btn", Wt::WString::tr("Lms.PlayQueue.template.shuffle-btn"), Wt::TextFormat::XHTML);
|
Wt::WText* shuffleBtn = bindNew<Wt::WText>("shuffle-btn", Wt::WString::tr("Lms.PlayQueue.template.shuffle-btn"), Wt::TextFormat::XHTML);
|
||||||
setToolTip(*shuffleBtn, Wt::WString::tr("Lms.PlayQueue.shuffle"));
|
|
||||||
shuffleBtn->clicked().connect([=]
|
shuffleBtn->clicked().connect([=]
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -95,33 +81,33 @@ PlayQueue::PlayQueue()
|
|||||||
addSome();
|
addSome();
|
||||||
});
|
});
|
||||||
|
|
||||||
_repeatBtn = bindNew<Wt::WText>("repeat-btn", Wt::WString::tr("Lms.PlayQueue.template.repeat-btn"), Wt::TextFormat::XHTML);
|
_repeatBtn = bindNew<Wt::WCheckBox>("repeat-btn");
|
||||||
setToolTip(*_repeatBtn, Wt::WString::tr("Lms.PlayQueue.repeat"));
|
|
||||||
_repeatBtn->clicked().connect([=]
|
_repeatBtn->clicked().connect([=]
|
||||||
{
|
{
|
||||||
_repeatAll = !_repeatAll;
|
|
||||||
updateRepeatBtn();
|
|
||||||
|
|
||||||
auto transaction {LmsApp->getDbSession().createUniqueTransaction()};
|
auto transaction {LmsApp->getDbSession().createUniqueTransaction()};
|
||||||
|
|
||||||
if (!LmsApp->getUser()->isDemo())
|
if (!LmsApp->getUser()->isDemo())
|
||||||
LmsApp->getUser().modify()->setRepeatAll(_repeatAll);
|
LmsApp->getUser().modify()->setRepeatAll(isRepeatAllSet());
|
||||||
});
|
});
|
||||||
updateRepeatBtn();
|
{
|
||||||
|
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||||
|
if (LmsApp->getUser()->isRepeatAllSet())
|
||||||
|
_repeatBtn->setCheckState(Wt::CheckState::Checked);
|
||||||
|
}
|
||||||
|
|
||||||
_radioBtn = bindNew<Wt::WText>("radio-btn", Wt::WString::tr("Lms.PlayQueue.template.radio-btn"));
|
_radioBtn = bindNew<Wt::WCheckBox>("radio-btn");
|
||||||
setToolTip(*_radioBtn, Wt::WString::tr("Lms.PlayQueue.radio-mode"));
|
|
||||||
_radioBtn->clicked().connect([=]
|
_radioBtn->clicked().connect([=]
|
||||||
{
|
{
|
||||||
_radioMode = !_radioMode;
|
|
||||||
updateRadioBtn();
|
|
||||||
|
|
||||||
auto transaction {LmsApp->getDbSession().createUniqueTransaction()};
|
auto transaction {LmsApp->getDbSession().createUniqueTransaction()};
|
||||||
|
|
||||||
if (!LmsApp->getUser()->isDemo())
|
if (!LmsApp->getUser()->isDemo())
|
||||||
LmsApp->getUser().modify()->setRadio(_radioMode);
|
LmsApp->getUser().modify()->setRadio(isRadioModeSet());
|
||||||
});
|
});
|
||||||
updateRadioBtn();
|
{
|
||||||
|
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||||
|
if (LmsApp->getUser()->isRadioSet())
|
||||||
|
_radioBtn->setCheckState(Wt::CheckState::Checked);
|
||||||
|
}
|
||||||
|
|
||||||
_nbTracks = bindNew<Wt::WText>("nb-tracks");
|
_nbTracks = bindNew<Wt::WText>("nb-tracks");
|
||||||
|
|
||||||
@@ -180,18 +166,16 @@ PlayQueue::PlayQueue()
|
|||||||
addSome();
|
addSome();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
PlayQueue::updateRepeatBtn()
|
PlayQueue::isRepeatAllSet() const
|
||||||
{
|
{
|
||||||
_repeatBtn->toggleStyleClass("text-success", _repeatAll);
|
return _repeatBtn->checkState() == Wt::CheckState::Checked;
|
||||||
_repeatBtn->toggleStyleClass("text-muted", !_repeatAll);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
PlayQueue::updateRadioBtn()
|
PlayQueue::isRadioModeSet() const
|
||||||
{
|
{
|
||||||
_radioBtn->toggleStyleClass("text-success",_radioMode);
|
return _radioBtn->checkState() == Wt::CheckState::Checked;
|
||||||
_radioBtn->toggleStyleClass("text-muted", !_radioMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::TrackList::pointer
|
Database::TrackList::pointer
|
||||||
@@ -243,7 +227,7 @@ PlayQueue::loadTrack(std::size_t pos, bool play)
|
|||||||
// If out of range, stop playing
|
// If out of range, stop playing
|
||||||
if (pos >= tracklist->getCount())
|
if (pos >= tracklist->getCount())
|
||||||
{
|
{
|
||||||
if (!_repeatAll || tracklist->getCount() == 0)
|
if (!isRepeatAllSet() || tracklist->getCount() == 0)
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
@@ -253,7 +237,7 @@ PlayQueue::loadTrack(std::size_t pos, bool play)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If last and radio mode, fill the next song
|
// If last and radio mode, fill the next song
|
||||||
if (_radioMode && pos == tracklist->getCount() - 1)
|
if (isRadioModeSet() && pos == tracklist->getCount() - 1)
|
||||||
addRadioTrack = true;
|
addRadioTrack = true;
|
||||||
|
|
||||||
_trackPos = pos;
|
_trackPos = pos;
|
||||||
@@ -313,9 +297,9 @@ PlayQueue::updateCurrentTrack(bool selected)
|
|||||||
if (!_trackPos || *_trackPos >= static_cast<std::size_t>(_entriesContainer->getCount()))
|
if (!_trackPos || *_trackPos >= static_cast<std::size_t>(_entriesContainer->getCount()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Wt::WTemplate* entry {static_cast<Wt::WTemplate*>(_entriesContainer->getWidget(*_trackPos))};
|
Template* entry {static_cast<Template*>(_entriesContainer->getWidget(*_trackPos))};
|
||||||
if (entry)
|
if (entry)
|
||||||
entry->bindString("is-selected", selected ? "Lms-playqueue-selected" : "");
|
entry->bindString("is-playing", selected ? "TODO" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
std::size_t
|
||||||
@@ -410,37 +394,22 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry)
|
|||||||
const auto track {tracklistEntry->getTrack()};
|
const auto track {tracklistEntry->getTrack()};
|
||||||
const Database::TrackId trackId {track->getId()};
|
const Database::TrackId trackId {track->getId()};
|
||||||
|
|
||||||
Wt::WTemplate* entry = _entriesContainer->addNew<Wt::WTemplate>(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->bindString("is-selected", "");
|
entry->bindEmpty("is-playing");
|
||||||
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
|
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
|
||||||
|
|
||||||
const auto artists {track->getArtists({Database::TrackArtistLinkType::Artist})};
|
|
||||||
const auto release {track->getRelease()};
|
const auto release {track->getRelease()};
|
||||||
|
|
||||||
if (!artists.empty() || release)
|
|
||||||
entry->setCondition("if-has-artists-or-release", true);
|
|
||||||
|
|
||||||
if (!artists.empty())
|
|
||||||
{
|
|
||||||
entry->setCondition("if-has-artists", true);
|
|
||||||
|
|
||||||
Wt::WContainerWidget* artistContainer {entry->bindNew<Wt::WContainerWidget>("artists")};
|
|
||||||
for (const auto& artist : artists)
|
|
||||||
{
|
|
||||||
Wt::WTemplate* a {artistContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.PlayQueue.template.entry-artist"))};
|
|
||||||
a->bindWidget("artist", LmsApplication::createArtistAnchor(artist));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (release)
|
if (release)
|
||||||
{
|
{
|
||||||
entry->setCondition("if-has-release", true);
|
entry->setCondition("if-has-release", true);
|
||||||
entry->bindWidget("release", LmsApplication::createReleaseAnchor(release));
|
entry->bindWidget("release", LmsApplication::createReleaseAnchor(release));
|
||||||
{
|
{
|
||||||
Wt::WAnchor* anchor = entry->bindWidget("cover", LmsApplication::createReleaseAnchor(release, false));
|
Wt::WAnchor* anchor {entry->bindWidget("cover", LmsApplication::createReleaseAnchor(release, false))};
|
||||||
auto cover = std::make_unique<Wt::WImage>();
|
auto cover {std::make_unique<Wt::WImage>()};
|
||||||
cover->setImageLink(LmsApp->getCoverResource()->getReleaseUrl(release->getId(), CoverResource::Size::Large));
|
cover->setImageLink(LmsApp->getCoverResource()->getReleaseUrl(release->getId(), CoverResource::Size::Large));
|
||||||
cover->setStyleClass("img-fluid");
|
cover->setStyleClass("img-fluid"); // HACK
|
||||||
cover->setAttributeValue("onload", LmsApp->javaScriptClass() + ".onLoadCover(this)");
|
cover->setAttributeValue("onload", LmsApp->javaScriptClass() + ".onLoadCover(this)");
|
||||||
anchor->setImage(std::move(cover));
|
anchor->setImage(std::move(cover));
|
||||||
}
|
}
|
||||||
@@ -449,7 +418,7 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry)
|
|||||||
{
|
{
|
||||||
auto cover = entry->bindNew<Wt::WImage>("cover");
|
auto cover = entry->bindNew<Wt::WImage>("cover");
|
||||||
cover->setImageLink(LmsApp->getCoverResource()->getTrackUrl(track->getId(), CoverResource::Size::Large));
|
cover->setImageLink(LmsApp->getCoverResource()->getTrackUrl(track->getId(), CoverResource::Size::Large));
|
||||||
cover->setStyleClass("img-fluid");
|
cover->setStyleClass("img-fluid"); // HACK
|
||||||
cover->setAttributeValue("onload", LmsApp->javaScriptClass() + ".onLoadCover(this)");
|
cover->setAttributeValue("onload", LmsApp->javaScriptClass() + ".onLoadCover(this)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,26 +455,29 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry)
|
|||||||
updateInfo();
|
updateInfo();
|
||||||
});
|
});
|
||||||
|
|
||||||
Wt::WText* moreBtn {entry->bindNew<Wt::WText>("more-btn", Wt::WString::tr("Lms.PlayQueue.template.more-btn"), Wt::TextFormat::XHTML)};
|
entry->bindNew<Wt::WText>("more-btn", Wt::WString::tr("Lms.PlayQueue.template.more-btn"), Wt::TextFormat::XHTML);
|
||||||
moreBtn->clicked().connect([=]
|
|
||||||
{
|
|
||||||
/* Wt::WPopupMenu* popup {LmsApp->createPopupMenu()};
|
|
||||||
|
|
||||||
const bool isStarred {Service<Scrobbling::IScrobblingService>::get()->isStarred(LmsApp->getUserId(), trackId)};
|
auto isStarred {[=] { return Service<Scrobbling::IScrobblingService>::get()->isStarred(LmsApp->getUserId(), trackId); }};
|
||||||
popup->addItem(Wt::WString::tr(isStarred ? "Lms.Explore.unstar" : "Lms.Explore.star"))
|
|
||||||
->triggered().connect(moreBtn, [=]
|
Wt::WPushButton* starBtn {entry->bindNew<Wt::WPushButton>("star", Wt::WString::tr(isStarred() ? "Lms.Explore.unstar" : "Lms.Explore.star"))};
|
||||||
|
starBtn->clicked().connect([=]
|
||||||
|
{
|
||||||
|
auto transaction {LmsApp->getDbSession().createUniqueTransaction()};
|
||||||
|
|
||||||
|
if (isStarred())
|
||||||
{
|
{
|
||||||
if (isStarred)
|
|
||||||
Service<Scrobbling::IScrobblingService>::get()->unstar(LmsApp->getUserId(), trackId);
|
Service<Scrobbling::IScrobblingService>::get()->unstar(LmsApp->getUserId(), trackId);
|
||||||
|
starBtn->setText(Wt::WString::tr("Lms.Explore.star"));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Service<Scrobbling::IScrobblingService>::get()->star(LmsApp->getUserId(), trackId);
|
Service<Scrobbling::IScrobblingService>::get()->star(LmsApp->getUserId(), trackId);
|
||||||
|
starBtn->setText(Wt::WString::tr("Lms.Explore.unstar"));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
popup->addItem(Wt::WString::tr("Lms.Explore.download"))
|
|
||||||
->setLink(Wt::WLink {std::make_unique<DownloadTrackResource>(trackId)});
|
|
||||||
|
|
||||||
popup->popup(moreBtn);
|
entry->bindNew<Wt::WPushButton>("download", Wt::WString::tr("Lms.Explore.download"))
|
||||||
*/
|
->setLink(Wt::WLink {std::make_unique<DownloadTrackResource>(trackId)});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#include <Wt/WCheckBox.h>
|
||||||
#include <Wt/WContainerWidget.h>
|
#include <Wt/WContainerWidget.h>
|
||||||
#include <Wt/WTemplate.h>
|
#include <Wt/WTemplate.h>
|
||||||
#include <Wt/WText.h>
|
#include <Wt/WText.h>
|
||||||
@@ -29,6 +30,8 @@
|
|||||||
#include "services/database/TrackListId.hpp"
|
#include "services/database/TrackListId.hpp"
|
||||||
#include "PlayQueueAction.hpp"
|
#include "PlayQueueAction.hpp"
|
||||||
|
|
||||||
|
#include "common/Template.hpp"
|
||||||
|
|
||||||
namespace Similarity
|
namespace Similarity
|
||||||
{
|
{
|
||||||
class Finder;
|
class Finder;
|
||||||
@@ -45,7 +48,7 @@ namespace UserInterface {
|
|||||||
|
|
||||||
class InfiniteScrollingContainer;
|
class InfiniteScrollingContainer;
|
||||||
|
|
||||||
class PlayQueue : public Wt::WTemplate
|
class PlayQueue : public Template
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayQueue();
|
PlayQueue();
|
||||||
@@ -75,8 +78,8 @@ class PlayQueue : public Wt::WTemplate
|
|||||||
void enqueueRadioTracks();
|
void enqueueRadioTracks();
|
||||||
void updateInfo();
|
void updateInfo();
|
||||||
void updateCurrentTrack(bool selected);
|
void updateCurrentTrack(bool selected);
|
||||||
void updateRepeatBtn();
|
bool isRepeatAllSet() const;
|
||||||
void updateRadioBtn();
|
bool isRadioModeSet() const;
|
||||||
|
|
||||||
void loadTrack(std::size_t pos, bool play);
|
void loadTrack(std::size_t pos, bool play);
|
||||||
void stop();
|
void stop();
|
||||||
@@ -88,14 +91,12 @@ class PlayQueue : public Wt::WTemplate
|
|||||||
static inline constexpr std::size_t _nbMaxEntries {1000};
|
static inline constexpr std::size_t _nbMaxEntries {1000};
|
||||||
static inline constexpr std::size_t _batchSize {12};
|
static inline constexpr std::size_t _batchSize {12};
|
||||||
|
|
||||||
bool _repeatAll {};
|
|
||||||
bool _radioMode {};
|
|
||||||
bool _mediaPlayerSettingsLoaded {};
|
bool _mediaPlayerSettingsLoaded {};
|
||||||
Database::TrackListId _tracklistId {};
|
Database::TrackListId _tracklistId {};
|
||||||
InfiniteScrollingContainer* _entriesContainer {};
|
InfiniteScrollingContainer* _entriesContainer {};
|
||||||
Wt::WText* _nbTracks {};
|
Wt::WText* _nbTracks {};
|
||||||
Wt::WText* _repeatBtn {};
|
Wt::WCheckBox* _repeatBtn {};
|
||||||
Wt::WText* _radioBtn {};
|
Wt::WCheckBox* _radioBtn {};
|
||||||
std::optional<std::size_t> _trackPos; // current track position, if set
|
std::optional<std::size_t> _trackPos; // current track position, if set
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace UserInterface
|
|||||||
void addSome();
|
void addSome();
|
||||||
|
|
||||||
static constexpr std::size_t _batchSize {30};
|
static constexpr std::size_t _batchSize {30};
|
||||||
static constexpr std::size_t _maxCount {256};
|
static constexpr std::size_t _maxCount {512};
|
||||||
|
|
||||||
Wt::WWidget* _currentActiveItem {};
|
Wt::WWidget* _currentActiveItem {};
|
||||||
InfiniteScrollingContainer* _container {};
|
InfiniteScrollingContainer* _container {};
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ namespace UserInterface
|
|||||||
};
|
};
|
||||||
static inline std::unordered_map<Mode, std::size_t> _maxCounts
|
static inline std::unordered_map<Mode, std::size_t> _maxCounts
|
||||||
{
|
{
|
||||||
{Mode::Artist, 64},
|
{Mode::Artist, 512},
|
||||||
{Mode::Release, 60},
|
{Mode::Release, 60},
|
||||||
{Mode::Track, 64},
|
{Mode::Track, 64},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user