diff --git a/approot/playqueue.xml b/approot/playqueue.xml index b1c4424e..0633bcbf 100644 --- a/approot/playqueue.xml +++ b/approot/playqueue.xml @@ -8,14 +8,13 @@ + + ${clear-btn class="Lms-playqueue-btn Lms-btn"}${shuffle-btn class="Lms-playqueue-btn Lms-btn"}${repeat-btn class="Lms-playqueue-btn Lms-btn"}${radio-btn class="Lms-playqueue-btn Lms-btn"} + ${nb-tracks} + - - ${clear-btn class="Lms-playqueue-btn Lms-btn"}${shuffle-btn class="Lms-playqueue-btn Lms-btn"}${repeat-btn class="Lms-playqueue-btn Lms-btn"}${radio-btn class="Lms-playqueue-btn Lms-btn"} - ${nb-tracks} - ${entries} - ${loading-indicator class="Lms-horizontal-center Lms-loading-indicator"} diff --git a/src/lms/ui/PlayQueue.cpp b/src/lms/ui/PlayQueue.cpp index d4a790cd..e9d17ea9 100644 --- a/src/lms/ui/PlayQueue.cpp +++ b/src/lms/ui/PlayQueue.cpp @@ -33,7 +33,7 @@ #include "utils/Service.hpp" #include "utils/String.hpp" -#include "common/LoadingIndicator.hpp" +#include "common/InfiniteScrollingContainer.hpp" #include "resource/CoverResource.hpp" #include "resource/DownloadResource.hpp" #include "LmsApplication.hpp" @@ -67,8 +67,12 @@ PlayQueue::PlayQueue() clearTracks(); }); - _entriesContainer = bindNew("entries"); - hideLoadingIndicator(); + _entriesContainer = bindNew("entries"); + _entriesContainer->onRequestElements.connect([this] + { + addSome(); + updateCurrentTrack(true); + }); Wt::WText* shuffleBtn = bindNew("shuffle-btn", Wt::WString::tr("Lms.PlayQueue.template.shuffle-btn"), Wt::TextFormat::XHTML); setToolTip(*shuffleBtn, Wt::WString::tr("Lms.PlayQueue.shuffle")); @@ -184,27 +188,6 @@ PlayQueue::updateRadioBtn() _radioBtn->toggleStyleClass("text-muted", !_radioMode); } -void -PlayQueue::displayLoadingIndicator() -{ - _loadingIndicator = bindWidget("loading-indicator", createLoadingIndicator()); - _loadingIndicator->scrollVisibilityChanged().connect([this](bool visible) - { - if (!visible) - return; - - addSome(); - updateCurrentTrack(true); - }); -} - -void -PlayQueue::hideLoadingIndicator() -{ - _loadingIndicator = nullptr; - bindEmpty("loading-indicator"); -} - Database::TrackList::pointer PlayQueue::getTrackList() const { @@ -226,7 +209,6 @@ PlayQueue::clearTracks() getTrackList().modify()->clear(); } - hideLoadingIndicator(); _entriesContainer->clear(); updateInfo(); } @@ -322,10 +304,10 @@ PlayQueue::updateInfo() void PlayQueue::updateCurrentTrack(bool selected) { - if (!_trackPos || *_trackPos >= static_cast(_entriesContainer->count())) + if (!_trackPos || *_trackPos >= static_cast(_entriesContainer->getCount())) return; - Wt::WTemplate* entry {static_cast(_entriesContainer->widget(*_trackPos))}; + Wt::WTemplate* entry {static_cast(_entriesContainer->getWidget(*_trackPos))}; if (entry) entry->bindString("is-selected", selected ? "Lms-playqueue-selected" : ""); } @@ -410,14 +392,11 @@ PlayQueue::addSome() auto tracklist = getTrackList(); - auto tracklistEntries = tracklist->getEntries(_entriesContainer->count(), 50); + auto tracklistEntries = tracklist->getEntries(_entriesContainer->getCount(), 50); for (const Database::TrackListEntry::pointer& tracklistEntry : tracklistEntries) addEntry(tracklistEntry); - if (static_cast(_entriesContainer->count()) < tracklist->getCount()) - displayLoadingIndicator(); - else - hideLoadingIndicator(); + _entriesContainer->setHasMore(_entriesContainer->getCount() < tracklist->getCount()); } void @@ -474,9 +453,9 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry) Wt::WText* playBtn {entry->bindNew("play-btn", Wt::WString::tr("Lms.PlayQueue.template.play-btn"), Wt::TextFormat::XHTML)}; playBtn->clicked().connect([=] { - auto pos = _entriesContainer->indexOf(entry); - if (pos >= 0) - loadTrack(pos, true); + const std::optional pos {_entriesContainer->getIndexOf(*entry)}; + if (pos) + loadTrack(*pos, true); }); Wt::WText* delBtn {entry->bindNew("del-btn", Wt::WString::tr("Lms.PlayQueue.template.delete-btn"), Wt::TextFormat::XHTML)}; @@ -492,12 +471,12 @@ PlayQueue::addEntry(const Database::TrackListEntry::pointer& tracklistEntry) if (_trackPos) { - auto pos {_entriesContainer->indexOf(entry)}; - if (pos > 0 && *_trackPos >= static_cast(pos)) - (*_trackPos)--; + const std::optional pos {_entriesContainer->getIndexOf(*entry)}; + if (pos && *_trackPos >= *pos) + (*_trackPos)--; } - _entriesContainer->removeWidget(entry); + _entriesContainer->remove(*entry); updateInfo(); }); diff --git a/src/lms/ui/PlayQueue.hpp b/src/lms/ui/PlayQueue.hpp index 9a65c177..1ab611c5 100644 --- a/src/lms/ui/PlayQueue.hpp +++ b/src/lms/ui/PlayQueue.hpp @@ -28,11 +28,13 @@ #include "database/Types.hpp" #include "PlayQueueAction.hpp" -namespace Similarity { +namespace Similarity +{ class Finder; } -namespace Database { +namespace Database +{ class Track; class TrackList; class TrackListEntry; @@ -40,6 +42,8 @@ namespace Database { namespace UserInterface { +class InfiniteScrollingContainer; + class PlayQueue : public Wt::WTemplate { public: @@ -72,8 +76,6 @@ class PlayQueue : public Wt::WTemplate void updateCurrentTrack(bool selected); void updateRepeatBtn(); void updateRadioBtn(); - void displayLoadingIndicator(); - void hideLoadingIndicator(); void loadTrack(std::size_t pos, bool play); void stop(); @@ -88,8 +90,7 @@ class PlayQueue : public Wt::WTemplate bool _radioMode {}; bool _mediaPlayerSettingsLoaded {}; Database::IdType _tracklistId {}; - Wt::WContainerWidget* _entriesContainer {}; - Wt::WTemplate* _loadingIndicator {}; + InfiniteScrollingContainer* _entriesContainer {}; Wt::WText* _nbTracks {}; Wt::WText* _repeatBtn {}; Wt::WText* _radioBtn {}; diff --git a/src/lms/ui/common/InfiniteScrollingContainer.cpp b/src/lms/ui/common/InfiniteScrollingContainer.cpp index 954c3a28..aca5c057 100644 --- a/src/lms/ui/common/InfiniteScrollingContainer.cpp +++ b/src/lms/ui/common/InfiniteScrollingContainer.cpp @@ -59,6 +59,25 @@ namespace UserInterface hideLoadingIndicator(); } + void + InfiniteScrollingContainer::remove(Wt::WWidget& widget) + { + _elements->removeWidget(&widget); + } + + Wt::WWidget* + InfiniteScrollingContainer::getWidget(std::size_t pos) const + { + return _elements->widget(pos); + } + + std::optional + InfiniteScrollingContainer::getIndexOf(Wt::WWidget& widget) const + { + return _elements->indexOf(&widget); + } + + void InfiniteScrollingContainer::displayLoadingIndicator() { @@ -79,5 +98,4 @@ namespace UserInterface bindEmpty("loading-indicator"); } - } diff --git a/src/lms/ui/common/InfiniteScrollingContainer.hpp b/src/lms/ui/common/InfiniteScrollingContainer.hpp index 48836b58..eae4fa7f 100644 --- a/src/lms/ui/common/InfiniteScrollingContainer.hpp +++ b/src/lms/ui/common/InfiniteScrollingContainer.hpp @@ -19,6 +19,9 @@ #pragma once +#include +#include + #include #include #include @@ -36,6 +39,17 @@ namespace UserInterface std::size_t getCount(); void add(std::unique_ptr result); + template + T* addNew(Args&&... args) + { + return _elements->addNew(std::forward(args)...); + } + + void remove(Wt::WWidget& widget); + + Wt::WWidget* getWidget(std::size_t pos) const; + std::optional getIndexOf(Wt::WWidget& widget) const; + void setHasMore(bool hasMore); Wt::Signal<> onRequestElements;