Split the search view in order to workaround the scroll visibility issue

This commit is contained in:
emeric
2023-11-03 09:12:19 +01:00
parent e339a42883
commit 9ff1b215c2
3 changed files with 207 additions and 186 deletions
+13 -13
View File
@@ -3,29 +3,29 @@
<!--FORMS message blocks-->
<message id="Lms.Explore.Search.template">
<ul class="nav nav-pills mb-3" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="releases-tab" data-bs-toggle="tab" data-bs-target="#releases" type="button" role="tab" aria-controls="releases" aria-selected="true">${tr:Lms.Explore.releases}</button>
<div class="mb-3">
<ul class="nav nav-pills mb-3">
<li class="nav-item">
${releases class="nav-link"}
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="artists-tab" data-bs-toggle="tab" data-bs-target="#artists" type="button" role="tab" aria-controls="artists" aria-selected="false">${tr:Lms.Explore.artists}</button>
<li class="nav-item">
${artists class="nav-link"}
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tracks-tab" data-bs-toggle="tab" data-bs-target="#tracks" type="button" role="tab" aria-controls="tracks" aria-selected="false">${tr:Lms.Explore.tracks}</button>
<li class="nav-item">
${tracks class="nav-link"}
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane show active" id="releases" role="tabpanel" aria-labelledby="releases-tab">${releases}</div>
<div class="tab-pane" id="artists" role="tabpanel" aria-labelledby="artists-tab">
</div>
${results}
</message>
<message id="Lms.Explore.Search.template.artists">
<div class="row mb-3">
<div class="col-lg-3">
${link-type class="form-select"}
</div>
</div>
${artists}
</div>
<div class="tab-pane" id="tracks" role="tabpanel" aria-labelledby="tracks-tab">${tracks}</div>
</div>
</message>
</messages>
+69 -47
View File
@@ -19,6 +19,8 @@
#include "SearchView.hpp"
#include <Wt/WPushButton.h>
#include "services/database/Artist.hpp"
#include "services/database/Release.hpp"
#include "services/database/Session.hpp"
@@ -36,32 +38,64 @@ using namespace Database;
namespace UserInterface
{
SearchView::SearchView(Filters& filters, PlayQueueController& playQueueController)
: Wt::WTemplate {Wt::WString::tr("Lms.Explore.Search.template")}
, _playQueueController {playQueueController}
, _filters {filters}
, _artistCollector {filters, ArtistCollector::Mode::Search, getMaxCount(Mode::Artist)}
, _releaseCollector {filters, ReleaseCollector::Mode::Search, getMaxCount(Mode::Release)}
, _trackCollector {filters, TrackCollector::Mode::Search, getMaxCount(Mode::Track)}
: Wt::WTemplate{ Wt::WString::tr("Lms.Explore.Search.template") }
, _playQueueController{ playQueueController }
, _filters{ filters }
, _artistCollector{ filters, ArtistCollector::Mode::Search, getMaxCount(Mode::Artist) }
, _releaseCollector{ filters, ReleaseCollector::Mode::Search, getMaxCount(Mode::Release) }
, _trackCollector{ filters, TrackCollector::Mode::Search, getMaxCount(Mode::Track) }
{
addFunction("tr", &Wt::WTemplate::Functions::tr);
_artists = bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container"));
_artists->onRequestElements.connect([this] { addSomeArtists(); });
_stack = bindNew<Wt::WStackedWidget>("results");
_artistLinkType = bindNew<Wt::WComboBox>("link-type");
// releases
_releases = _stack->addNew<InfiniteScrollingContainer>(Wt::WString::tr("Lms.Explore.Releases.template.container"));
_releases->onRequestElements.connect([this] { addSomeReleases(); });
// artists
{
Wt::WTemplate* artistResults{ _stack->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Search.template.artists")) };
_artistLinkType = artistResults->bindNew<Wt::WComboBox>("link-type");
_artistLinkType->setModel(ArtistListHelpers::createArtistLinkTypesModel());
_artistLinkType->changed().connect([this]
{
const std::optional<TrackArtistLinkType> linkType {static_cast<ArtistLinkTypesModel*>(_artistLinkType->model().get())->getValue(_artistLinkType->currentIndex())};
const std::optional<TrackArtistLinkType> linkType{ static_cast<ArtistLinkTypesModel*>(_artistLinkType->model().get())->getValue(_artistLinkType->currentIndex()) };
refreshView(linkType);
});
_releases = bindNew<InfiniteScrollingContainer>("releases", Wt::WString::tr("Lms.Explore.Releases.template.container"));
_releases->onRequestElements.connect([this] { addSomeReleases(); });
_artists = artistResults->bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container"));
_artists->onRequestElements.connect([this] { addSomeArtists(); });
}
_tracks = bindNew<InfiniteScrollingContainer>("tracks");
// Tracks
_tracks = _stack->addNew<InfiniteScrollingContainer>();
_tracks->onRequestElements.connect([this] { addSomeTracks(); });
// Menu
auto bindMenuItem{ [this](std::size_t index, const std::string& var, const Wt::WString& title)
{
Wt::WPushButton* menuItem {bindNew<Wt::WPushButton>(var, title)};
menuItem->clicked().connect([=]
{
_stack->setCurrentIndex(index);
_currentActiveItem->removeStyleClass("active");
menuItem->addStyleClass("active");
_currentActiveItem = menuItem;
});
if (index == 0)
{
_currentActiveItem = menuItem;
_currentActiveItem->addStyleClass("active");
}
} };
bindMenuItem(0, "releases", Wt::WString::tr("Lms.Explore.releases"));
bindMenuItem(1, "artists", Wt::WString::tr("Lms.Explore.artists"));
bindMenuItem(2, "tracks", Wt::WString::tr("Lms.Explore.tracks"));
filters.updated().connect([=]
{
refreshView();
@@ -74,31 +108,27 @@ namespace UserInterface
});
}
std::size_t
SearchView::getBatchSize(Mode mode) const
std::size_t SearchView::getBatchSize(Mode mode) const
{
auto it {_batchSizes.find(mode)};
auto it{ _batchSizes.find(mode) };
assert(it != _batchSizes.cend());
return it->second;
}
std::size_t
SearchView::getMaxCount(Mode mode) const
std::size_t SearchView::getMaxCount(Mode mode) const
{
auto it {_maxCounts.find(mode)};
auto it{ _maxCounts.find(mode) };
assert(it != _maxCounts.cend());
return it->second;
}
void
SearchView::refreshView(std::optional<TrackArtistLinkType> linkType)
void SearchView::refreshView(std::optional<TrackArtistLinkType> linkType)
{
_artistCollector.setArtistLinkType(linkType);
refreshView();
}
void
SearchView::refreshView(const Wt::WString& searchText)
void SearchView::refreshView(const Wt::WString& searchText)
{
_releaseCollector.setSearch(searchText.toUTF8());
_artistCollector.setSearch(searchText.toUTF8());
@@ -106,68 +136,60 @@ namespace UserInterface
refreshView();
}
void
SearchView::refreshView()
void SearchView::refreshView()
{
_artists->reset();
_releases->reset();
_tracks->reset();
addSomeArtists();
addSomeReleases();
addSomeTracks();
}
void
SearchView::addSomeArtists()
void SearchView::addSomeArtists()
{
using namespace Database;
const Range range {_artists->getCount(), getBatchSize(Mode::Artist)};
const RangeResults<ArtistId> artistIds {_artistCollector.get(range)};
const Range range{ _artists->getCount(), getBatchSize(Mode::Artist) };
const RangeResults<ArtistId> artistIds{ _artistCollector.get(range) };
{
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
for (const ArtistId artistId : artistIds.results)
{
const Artist::pointer artist {Artist::find(LmsApp->getDbSession(), artistId)};
const Artist::pointer artist{ Artist::find(LmsApp->getDbSession(), artistId) };
_artists->add(ArtistListHelpers::createEntry(artist));
}
}
}
void
SearchView::addSomeReleases()
void SearchView::addSomeReleases()
{
using namespace Database;
const Range range {_releases->getCount(), getBatchSize(Mode::Release)};
const RangeResults<ReleaseId> releaseIds {_releaseCollector.get(range)};
const Range range{ _releases->getCount(), getBatchSize(Mode::Release) };
const RangeResults<ReleaseId> releaseIds{ _releaseCollector.get(range) };
{
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
for (const ReleaseId releaseId : releaseIds.results)
{
const Release::pointer release {Release::find(LmsApp->getDbSession(), releaseId)};
const Release::pointer release{ Release::find(LmsApp->getDbSession(), releaseId) };
_releases->add(ReleaseListHelpers::createEntry(release));
}
}
}
void
SearchView::addSomeTracks()
void SearchView::addSomeTracks()
{
using namespace Database;
const Range range {_tracks->getCount(), getBatchSize(Mode::Track)};
const RangeResults<TrackId> trackIds {_trackCollector.get(range)};
const Range range{ _tracks->getCount(), getBatchSize(Mode::Track) };
const RangeResults<TrackId> trackIds{ _trackCollector.get(range) };
{
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
auto transaction{ LmsApp->getDbSession().createSharedTransaction() };
for (const TrackId trackId : trackIds.results)
{
const Track::pointer track {Track::find(LmsApp->getDbSession(), trackId)};
const Track::pointer track{ Track::find(LmsApp->getDbSession(), trackId) };
_tracks->add(TrackListHelpers::createEntry(track, _playQueueController, _filters));
}
}
+7 -8
View File
@@ -53,7 +53,7 @@ namespace UserInterface
Track,
};
static constexpr Mode _defaultMode {Mode::Release};
static constexpr Mode _defaultMode{ Mode::Release };
static inline std::unordered_map<Mode, std::size_t> _batchSizes
{
{Mode::Artist, 6},
@@ -80,14 +80,13 @@ namespace UserInterface
ArtistCollector _artistCollector;
ReleaseCollector _releaseCollector;
TrackCollector _trackCollector;
Wt::WStackedWidget* _stack{};
Wt::WWidget* _currentActiveItem {};
InfiniteScrollingContainer* _artists{};
InfiniteScrollingContainer* _releases{};
InfiniteScrollingContainer* _tracks{};
InfiniteScrollingContainer* _artists {};
InfiniteScrollingContainer* _releases {};
InfiniteScrollingContainer* _tracks {};
Wt::WComboBox* _artistLinkType {};
std::vector<InfiniteScrollingContainer*> _results;
Wt::WComboBox* _artistLinkType{};
};
} // namespace UserInterface