Removed the dedicated search view, as it is actually too limiting. Added a search field in the album/artists/tracks views. This makes search now work together with sort mode

This commit is contained in:
emeric
2024-05-01 15:21:48 +02:00
parent 971b6d9d08
commit dd5dfaa96e
29 changed files with 132 additions and 418 deletions
+4 -1
View File
@@ -4,9 +4,12 @@
<message id="Lms.Explore.Artists.template"> <message id="Lms.Explore.Artists.template">
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="d-flex justify-content-between align-items-center mb-3">
${link-type} ${link-type class="me-1"}
<div class="d-flex">
${search class="form-control me-1" type="search"}
${sort-mode} ${sort-mode}
</div> </div>
</div>
${artists} ${artists}
</message> </message>
-3
View File
@@ -14,9 +14,6 @@
<message id="Lms.main.template.navbar"> <message id="Lms.main.template.navbar">
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-3"> <nav class="navbar navbar-expand-md navbar-dark bg-dark mb-3">
<div class="container"> <div class="container">
<div class="d-flex">
${search class="form-control" type="search"}
</div>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
+4 -1
View File
@@ -4,7 +4,7 @@
<message id="Lms.Explore.Releases.template"> <message id="Lms.Explore.Releases.template">
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="d-flex justify-content-between align-items-center mb-3">
<div class="btn-group"> <div class="btn-group me-1">
${play-btn class="btn btn-primary"} ${play-btn class="btn btn-primary"}
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"/> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"/>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
@@ -13,8 +13,11 @@
<li>${play-shuffled class="dropdown-item"}</li> <li>${play-shuffled class="dropdown-item"}</li>
</ul> </ul>
</div> </div>
<div class="d-flex">
${search class="form-control me-1" type="search"}
${sort-mode} ${sort-mode}
</div> </div>
</div>
${releases} ${releases}
</message> </message>
-29
View File
@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<messages xmlns:if="Wt.WTemplate.conditions">
<!--FORMS message blocks-->
<message id="Lms.Explore.Search.template">
<div class="mb-3">
<ul class="nav nav-pills mb-3">
<li class="nav-item">
${releases class="nav-link"}
</li>
<li class="nav-item">
${artists class="nav-link"}
</li>
<li class="nav-item">
${tracks class="nav-link"}
</li>
</ul>
</div>
${results}
</message>
<message id="Lms.Explore.Search.template.artists">
<div class="mb-3">
${link-type}
</div>
${artists}
</message>
</messages>
+4 -1
View File
@@ -5,7 +5,7 @@
<message id="Lms.Explore.Tracks.template"> <message id="Lms.Explore.Tracks.template">
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="d-flex justify-content-between align-items-center mb-3">
<div class="btn-group"> <div class="btn-group me-1">
${play-btn class="btn btn-primary"} ${play-btn class="btn btn-primary"}
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"/> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"/>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
@@ -14,8 +14,11 @@
<li>${play-shuffled class="dropdown-item"}</li> <li>${play-shuffled class="dropdown-item"}</li>
</ul> </ul>
</div> </div>
<div class="d-flex">
${search class="form-control me-1" type="search"}
${sort-mode} ${sort-mode}
</div> </div>
</div>
${tracks} ${tracks}
</message> </message>
+30 -2
View File
@@ -32,9 +32,8 @@ namespace lms::db
Wt::Dbo::Query<ArtistId> createArtistsQuery(Session& session, const Listen::ArtistStatsFindParameters& params) Wt::Dbo::Query<ArtistId> createArtistsQuery(Session& session, const Listen::ArtistStatsFindParameters& params)
{ {
auto query{ session.getDboSession()->query<ArtistId>("SELECT a.id from artist a") auto query{ session.getDboSession()->query<ArtistId>("SELECT a.id from artist a")
.join("track t ON t.id = t_a_l.track_id")
.join("track_artist_link t_a_l ON t_a_l.artist_id = a.id") .join("track_artist_link t_a_l ON t_a_l.artist_id = a.id")
.join("listen l ON l.track_id = t.id") }; .join("listen l ON l.track_id = t_a_l.track_id") };
if (params.user.isValid()) if (params.user.isValid())
query.where("l.user_id = ?").bind(params.user); query.where("l.user_id = ?").bind(params.user);
@@ -45,7 +44,10 @@ namespace lms::db
assert(!params.artist.isValid()); // poor check assert(!params.artist.isValid()); // poor check
if (params.library.isValid()) if (params.library.isValid())
{
query.join("track t ON t.id = t_a_l.track_id");
query.where("t.media_library_id = ?").bind(params.library); query.where("t.media_library_id = ?").bind(params.library);
}
if (params.linkType) if (params.linkType)
query.where("t_a_l.type = ?").bind(*params.linkType); query.where("t_a_l.type = ?").bind(*params.linkType);
@@ -69,6 +71,26 @@ namespace lms::db
query.where(oss.str()); query.where(oss.str());
} }
if (!params.keywords.empty())
{
std::vector<std::string> clauses;
std::vector<std::string> sortClauses;
for (const std::string_view keyword : params.keywords)
{
clauses.push_back("a.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'");
query.bind("%" + utils::escapeLikeKeyword(keyword) + "%");
}
for (const std::string_view keyword : params.keywords)
{
sortClauses.push_back("a.sort_name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'");
query.bind("%" + utils::escapeLikeKeyword(keyword) + "%");
}
query.where("(" + core::stringUtils::joinStrings(clauses, " AND ") + ") OR (" + core::stringUtils::joinStrings(sortClauses, " AND ") + ")");
}
return query; return query;
} }
@@ -114,6 +136,9 @@ namespace lms::db
query.where(oss.str()); query.where(oss.str());
} }
for (std::string_view keyword : params.keywords)
query.where("r.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeLikeKeyword(keyword) + "%");
return query; return query;
} }
@@ -157,6 +182,9 @@ namespace lms::db
query.where(oss.str()); query.where(oss.str());
} }
for (std::string_view keyword : params.keywords)
query.where("t.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeLikeKeyword(keyword) + "%");
return query; return query;
} }
} }
@@ -70,6 +70,7 @@ namespace lms::db
UserId user; UserId user;
std::optional<ScrobblingBackend> backend; std::optional<ScrobblingBackend> backend;
std::vector<ClusterId> clusters; // if non empty, entities that belong to these clusters std::vector<ClusterId> clusters; // if non empty, entities that belong to these clusters
std::vector<std::string_view> keywords; // if non empty, name must match all of these keywords
std::optional<Range> range; std::optional<Range> range;
ArtistId artist; // if set, matching this artist ArtistId artist; // if set, matching this artist
MediaLibraryId library; MediaLibraryId library;
@@ -77,6 +78,7 @@ namespace lms::db
StatsFindParameters& setUser(UserId _user) { user = _user; return *this; } StatsFindParameters& setUser(UserId _user) { user = _user; return *this; }
StatsFindParameters& setScrobblingBackend(std::optional<ScrobblingBackend> _backend) { backend = _backend; return *this; } StatsFindParameters& setScrobblingBackend(std::optional<ScrobblingBackend> _backend) { backend = _backend; return *this; }
StatsFindParameters& setClusters(const std::vector<ClusterId>& _clusters) { clusters = _clusters; return *this; } StatsFindParameters& setClusters(const std::vector<ClusterId>& _clusters) { clusters = _clusters; return *this; }
StatsFindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
StatsFindParameters& setRange(std::optional<Range> _range) { range = _range; return *this; } StatsFindParameters& setRange(std::optional<Range> _range) { range = _range; return *this; }
StatsFindParameters& setArtist(ArtistId _artist) { artist = _artist; return *this; } StatsFindParameters& setArtist(ArtistId _artist) { artist = _artist; return *this; }
StatsFindParameters& setMediaLibrary(MediaLibraryId _library) { library = _library; return *this; } StatsFindParameters& setMediaLibrary(MediaLibraryId _library) { library = _library; return *this; }
@@ -96,6 +96,7 @@ namespace lms::feedback
Artist::FindParameters searchParams; Artist::FindParameters searchParams;
searchParams.setStarringUser(params.user, *backend); searchParams.setStarringUser(params.user, *backend);
searchParams.setClusters(params.clusters); searchParams.setClusters(params.clusters);
searchParams.setKeywords(params.keywords);
searchParams.setLinkType(params.linkType); searchParams.setLinkType(params.linkType);
searchParams.setSortMethod(params.sortMethod); searchParams.setSortMethod(params.sortMethod);
searchParams.setRange(params.range); searchParams.setRange(params.range);
@@ -136,6 +137,7 @@ namespace lms::feedback
Release::FindParameters searchParams; Release::FindParameters searchParams;
searchParams.setStarringUser(params.user, *backend); searchParams.setStarringUser(params.user, *backend);
searchParams.setClusters(params.clusters); searchParams.setClusters(params.clusters);
searchParams.setKeywords(params.keywords);
searchParams.setSortMethod(ReleaseSortMethod::StarredDateDesc); searchParams.setSortMethod(ReleaseSortMethod::StarredDateDesc);
searchParams.setRange(params.range); searchParams.setRange(params.range);
searchParams.setMediaLibrary(params.library); searchParams.setMediaLibrary(params.library);
@@ -175,6 +177,7 @@ namespace lms::feedback
Track::FindParameters searchParams; Track::FindParameters searchParams;
searchParams.setStarringUser(params.user, *backend); searchParams.setStarringUser(params.user, *backend);
searchParams.setClusters(params.clusters); searchParams.setClusters(params.clusters);
searchParams.setKeywords(params.keywords);
searchParams.setSortMethod(TrackSortMethod::StarredDateDesc); searchParams.setSortMethod(TrackSortMethod::StarredDateDesc);
searchParams.setRange(params.range); searchParams.setRange(params.range);
searchParams.setMediaLibrary(params.library); searchParams.setMediaLibrary(params.library);
@@ -54,11 +54,13 @@ namespace lms::feedback
{ {
db::UserId user; db::UserId user;
std::vector<db::ClusterId> clusters; // if non empty, at least one artist that belongs to these clusters std::vector<db::ClusterId> clusters; // if non empty, at least one artist that belongs to these clusters
std::vector<std::string_view> keywords; // if non empty, name must match all of these keywords
std::optional<db::Range> range; std::optional<db::Range> range;
db::MediaLibraryId library; db::MediaLibraryId library;
FindParameters& setUser(const db::UserId _user) { user = _user; return *this; } FindParameters& setUser(const db::UserId _user) { user = _user; return *this; }
FindParameters& setClusters(std::span<const db::ClusterId> _clusters) { clusters.assign(std::cbegin(_clusters), std::cend(_clusters)); return *this; } FindParameters& setClusters(std::span<const db::ClusterId> _clusters) { clusters.assign(std::cbegin(_clusters), std::cend(_clusters)); return *this; }
FindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
FindParameters& setRange(std::optional<db::Range> _range) { range = _range; return *this; } FindParameters& setRange(std::optional<db::Range> _range) { range = _range; return *this; }
FindParameters& setMediaLibrary(db::MediaLibraryId _library) { library = _library; return *this; } FindParameters& setMediaLibrary(db::MediaLibraryId _library) { library = _library; return *this; }
}; };
@@ -42,6 +42,7 @@ namespace lms::scrobbling
db::Listen::StatsFindParameters listenFindParams; db::Listen::StatsFindParameters listenFindParams;
listenFindParams.setUser(params.user); listenFindParams.setUser(params.user);
listenFindParams.setClusters(params.clusters); listenFindParams.setClusters(params.clusters);
listenFindParams.setKeywords(params.keywords);
listenFindParams.setRange(params.range); listenFindParams.setRange(params.range);
listenFindParams.setMediaLibrary(params.library); listenFindParams.setMediaLibrary(params.library);
listenFindParams.setArtist(params.artist); listenFindParams.setArtist(params.artist);
@@ -61,12 +61,14 @@ namespace lms::scrobbling
{ {
db::UserId user; db::UserId user;
std::vector<db::ClusterId> clusters; // if non empty, at least one artist that belongs to these clusters std::vector<db::ClusterId> clusters; // if non empty, at least one artist that belongs to these clusters
std::vector<std::string_view> keywords; // if non empty, name must match all of these keywords
std::optional<db::Range> range; std::optional<db::Range> range;
db::MediaLibraryId library; // if set, match this library db::MediaLibraryId library; // if set, match this library
db::ArtistId artist; // if set, match this artist db::ArtistId artist; // if set, match this artist
FindParameters& setUser(const db::UserId _user) { user = _user; return *this; } FindParameters& setUser(const db::UserId _user) { user = _user; return *this; }
FindParameters& setClusters(std::span<const db::ClusterId> _clusters) { clusters.assign(std::cbegin(_clusters), std::cend(_clusters)); return *this; } FindParameters& setClusters(std::span<const db::ClusterId> _clusters) { clusters.assign(std::cbegin(_clusters), std::cend(_clusters)); return *this; }
FindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
FindParameters& setRange(std::optional<db::Range> _range) { range = _range; return *this; } FindParameters& setRange(std::optional<db::Range> _range) { range = _range; return *this; }
FindParameters& setMediaLibrary(db::MediaLibraryId _library) { library = _library; return *this; } FindParameters& setMediaLibrary(db::MediaLibraryId _library) { library = _library; return *this; }
FindParameters& setArtist(db::ArtistId _artist) { artist = _artist; return *this; } FindParameters& setArtist(db::ArtistId _artist) { artist = _artist; return *this; }
-1
View File
@@ -42,7 +42,6 @@ add_executable(lms
ui/explore/ReleasesView.cpp ui/explore/ReleasesView.cpp
ui/explore/ReleaseView.cpp ui/explore/ReleaseView.cpp
ui/explore/ReleaseTypes.cpp ui/explore/ReleaseTypes.cpp
ui/explore/SearchView.cpp
ui/explore/SortModeSelector.cpp ui/explore/SortModeSelector.cpp
ui/explore/TrackArtistLinkTypeSelector.cpp ui/explore/TrackArtistLinkTypeSelector.cpp
ui/explore/TrackCollector.cpp ui/explore/TrackCollector.cpp
-16
View File
@@ -97,7 +97,6 @@ namespace lms::ui
res->use(appRoot + "playqueue"); res->use(appRoot + "playqueue");
res->use(appRoot + "release"); res->use(appRoot + "release");
res->use(appRoot + "releases"); res->use(appRoot + "releases");
res->use(appRoot + "search");
res->use(appRoot + "settings"); res->use(appRoot + "settings");
res->use(appRoot + "tracklist"); res->use(appRoot + "tracklist");
res->use(appRoot + "tracklists"); res->use(appRoot + "tracklists");
@@ -139,7 +138,6 @@ namespace lms::ui
{ "/artist", IdxExplore, false, std::nullopt }, { "/artist", IdxExplore, false, std::nullopt },
{ "/releases", IdxExplore, false, Wt::WString::tr("Lms.Explore.releases") }, { "/releases", IdxExplore, false, Wt::WString::tr("Lms.Explore.releases") },
{ "/release", IdxExplore, false, std::nullopt }, { "/release", IdxExplore, false, std::nullopt },
{ "/search", IdxExplore, false, Wt::WString::tr("Lms.Explore.search") },
{ "/tracks", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracks") }, { "/tracks", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracks") },
{ "/tracklists", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracklists") }, { "/tracklists", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracklists") },
{ "/tracklist", IdxExplore, false, std::nullopt }, { "/tracklist", IdxExplore, false, std::nullopt },
@@ -435,9 +433,6 @@ namespace lms::ui
logout->clicked().connect(this, &LmsApplication::logoutUser); logout->clicked().connect(this, &LmsApplication::logoutUser);
} }
Wt::WLineEdit* searchEdit{ navbar->bindNew<Wt::WLineEdit>("search") };
searchEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
if (LmsApp->getUserType() == db::UserType::ADMIN) if (LmsApp->getUserType() == db::UserType::ADMIN)
{ {
navbar->setCondition("if-is-admin", true); navbar->setCondition("if-is-admin", true);
@@ -462,17 +457,6 @@ namespace lms::ui
_playQueue = mainStack->addWidget(std::move(playQueue)); _playQueue = mainStack->addWidget(std::move(playQueue));
mainStack->addNew<SettingsView>(); mainStack->addNew<SettingsView>();
searchEdit->enterPressed().connect([this]
{
setInternalPath("/search", true);
});
searchEdit->textInput().connect([this, explore, searchEdit]
{
setInternalPath("/search", true);
explore->search(searchEdit->text());
});
// Admin stuff // Admin stuff
if (getUserType() == db::UserType::ADMIN) if (getUserType() == db::UserType::ADMIN)
{ {
+6 -16
View File
@@ -54,6 +54,7 @@ namespace lms::ui
feedback::IFeedbackService::ArtistFindParameters params; feedback::IFeedbackService::ArtistFindParameters params;
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(filters.getClusters()); params.setClusters(filters.getClusters());
params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary()); params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType); params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::StarredDateDesc); params.setSortMethod(ArtistSortMethod::StarredDateDesc);
@@ -67,6 +68,7 @@ namespace lms::ui
scrobbling::IScrobblingService::ArtistFindParameters params; scrobbling::IScrobblingService::ArtistFindParameters params;
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(filters.getClusters()); params.setClusters(filters.getClusters());
params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary()); params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType); params.setLinkType(_linkType);
params.setRange(range); params.setRange(range);
@@ -80,6 +82,7 @@ namespace lms::ui
scrobbling::IScrobblingService::ArtistFindParameters params; scrobbling::IScrobblingService::ArtistFindParameters params;
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(filters.getClusters()); params.setClusters(filters.getClusters());
params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary()); params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType); params.setLinkType(_linkType);
params.setRange(range); params.setRange(range);
@@ -92,6 +95,7 @@ namespace lms::ui
{ {
Artist::FindParameters params; Artist::FindParameters params;
params.setClusters(filters.getClusters()); params.setClusters(filters.getClusters());
params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary()); params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType); params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::LastWritten); params.setSortMethod(ArtistSortMethod::LastWritten);
@@ -104,27 +108,12 @@ namespace lms::ui
break; break;
} }
case Mode::Search:
{
Artist::FindParameters params;
params.setClusters(filters.getClusters());
params.setMediaLibrary(filters.getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setLinkType(_linkType);
params.setRange(range);
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
artists = Artist::findIds(LmsApp->getDbSession(), params);
}
break;
}
case Mode::All: case Mode::All:
{ {
Artist::FindParameters params; Artist::FindParameters params;
params.setClusters(filters.getClusters()); params.setClusters(filters.getClusters());
params.setMediaLibrary(filters.getMediaLibrary()); params.setMediaLibrary(filters.getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setLinkType(_linkType); params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::SortName); params.setSortMethod(ArtistSortMethod::SortName);
params.setRange(range); params.setRange(range);
@@ -152,6 +141,7 @@ namespace lms::ui
Artist::FindParameters params; Artist::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setLinkType(_linkType); params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::Random); params.setSortMethod(ArtistSortMethod::Random);
params.setRange(Range{ 0, getMaxCount() }); params.setRange(Range{ 0, getMaxCount() });
+15 -1
View File
@@ -38,10 +38,18 @@ namespace lms::ui
using namespace db; using namespace db;
Artists::Artists(Filters& filters) Artists::Artists(Filters& filters)
: Wt::WTemplate{ Wt::WString::tr("Lms.Explore.Artists.template") } : Template{ Wt::WString::tr("Lms.Explore.Artists.template") }
, _artistCollector{ filters, _defaultSortMode, _maxCount } , _artistCollector{ filters, _defaultSortMode, _maxCount }
{ {
addFunction("tr", &Wt::WTemplate::Functions::tr); addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("id", &Wt::WTemplate::Functions::id);
Wt::WLineEdit* searEdit{ bindNew<Wt::WLineEdit>("search") };
searEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
searEdit->textInput().connect([this, searEdit]
{
refreshView(searEdit->text());
});
SortModeSelector* sortModeSelector{ bindNew<SortModeSelector>("sort-mode", _defaultSortMode) }; SortModeSelector* sortModeSelector{ bindNew<SortModeSelector>("sort-mode", _defaultSortMode) };
sortModeSelector->sortModeChanged.connect([this](ArtistCollector::Mode sortMode) sortModeSelector->sortModeChanged.connect([this](ArtistCollector::Mode sortMode)
@@ -87,6 +95,12 @@ namespace lms::ui
refreshView(); refreshView();
} }
void Artists::refreshView(const Wt::WString& searchText)
{
_artistCollector.setSearch(searchText.toUTF8());
refreshView();
}
void Artists::addSome() void Artists::addSome()
{ {
const auto artistIds{ _artistCollector.get(Range {static_cast<std::size_t>(_container->getCount()), _batchSize}) }; const auto artistIds{ _artistCollector.get(Range {static_cast<std::size_t>(_container->getCount()), _batchSize}) };
+3 -1
View File
@@ -26,6 +26,7 @@
#include <Wt/WTemplate.h> #include <Wt/WTemplate.h>
#include "database/Types.hpp" #include "database/Types.hpp"
#include "common/Template.hpp"
#include "ArtistCollector.hpp" #include "ArtistCollector.hpp"
namespace lms::ui namespace lms::ui
@@ -33,7 +34,7 @@ namespace lms::ui
class Filters; class Filters;
class InfiniteScrollingContainer; class InfiniteScrollingContainer;
class Artists : public Wt::WTemplate class Artists : public Template
{ {
public: public:
Artists(Filters& filters); Artists(Filters& filters);
@@ -42,6 +43,7 @@ namespace lms::ui
void refreshView(); void refreshView();
void refreshView(ArtistCollector::Mode mode); void refreshView(ArtistCollector::Mode mode);
void refreshView(std::optional<db::TrackArtistLinkType> linkType); void refreshView(std::optional<db::TrackArtistLinkType> linkType);
void refreshView(const Wt::WString& searchText);
void addSome(); void addSome();
static constexpr std::size_t _batchSize{ 30 }; static constexpr std::size_t _batchSize{ 30 };
@@ -59,7 +59,10 @@ namespace lms::ui
void DatabaseCollectorBase::setSearch(std::string_view searchText) void DatabaseCollectorBase::setSearch(std::string_view searchText)
{ {
_searchText = searchText; _searchText = searchText;
if (!searchText.empty())
_searchKeywords = core::stringUtils::splitString(_searchText, ' '); _searchKeywords = core::stringUtils::splitString(_searchText, ' ');
else
_searchKeywords.clear();
} }
} // ns UserInterface } // ns UserInterface
@@ -45,7 +45,6 @@ namespace lms::ui
RecentlyPlayed, RecentlyPlayed,
RecentlyAdded, RecentlyAdded,
MostPlayed, MostPlayed,
Search,
All All
}; };
-12
View File
@@ -27,7 +27,6 @@
#include "Filters.hpp" #include "Filters.hpp"
#include "ReleasesView.hpp" #include "ReleasesView.hpp"
#include "ReleaseView.hpp" #include "ReleaseView.hpp"
#include "SearchView.hpp"
#include "TrackListView.hpp" #include "TrackListView.hpp"
#include "TrackListsView.hpp" #include "TrackListsView.hpp"
#include "TracksView.hpp" #include "TracksView.hpp"
@@ -46,7 +45,6 @@ namespace lms::ui
IdxTrackList, IdxTrackList,
IdxReleases, IdxReleases,
IdxRelease, IdxRelease,
IdxSearch,
IdxTracks, IdxTracks,
}; };
@@ -58,7 +56,6 @@ namespace lms::ui
{ "/tracklist", IdxTrackList }, { "/tracklist", IdxTrackList },
{ "/releases", IdxReleases }, { "/releases", IdxReleases },
{ "/release", IdxRelease }, { "/release", IdxRelease },
{ "/search", IdxSearch },
{ "/tracks", IdxTracks }, { "/tracks", IdxTracks },
}; };
@@ -103,10 +100,6 @@ namespace lms::ui
auto release = std::make_unique<Release>(filters, _playQueueController); auto release = std::make_unique<Release>(filters, _playQueueController);
contentsStack->addWidget(std::move(release)); contentsStack->addWidget(std::move(release));
auto search = std::make_unique<SearchView>(filters, _playQueueController);
_search = search.get();
contentsStack->addWidget(std::move(search));
auto tracks = std::make_unique<Tracks>(filters, _playQueueController); auto tracks = std::make_unique<Tracks>(filters, _playQueueController);
contentsStack->addWidget(std::move(tracks)); contentsStack->addWidget(std::move(tracks));
@@ -117,9 +110,4 @@ namespace lms::ui
handleContentsPathChange(contentsStack); handleContentsPathChange(contentsStack);
} }
void Explore::search(const Wt::WString& searchText)
{
_search->refreshView(searchText);
}
} // namespace lms::ui } // namespace lms::ui
-1
View File
@@ -34,7 +34,6 @@ namespace lms::ui
public: public:
Explore(Filters& filters, PlayQueue& playQueue); Explore(Filters& filters, PlayQueue& playQueue);
void search(const Wt::WString& searchText);
PlayQueueController& getPlayQueueController() { return _playQueueController; } PlayQueueController& getPlayQueueController() { return _playQueueController; }
private: private:
+6 -15
View File
@@ -53,6 +53,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
releases = feedbackService.findStarredReleases(params); releases = feedbackService.findStarredReleases(params);
break; break;
@@ -64,6 +65,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
releases = scrobblingService.getRecentReleases(params); releases = scrobblingService.getRecentReleases(params);
@@ -76,6 +78,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
releases = scrobblingService.getTopReleases(params); releases = scrobblingService.getTopReleases(params);
@@ -83,26 +86,12 @@ namespace lms::ui
} }
case Mode::RecentlyAdded: case Mode::RecentlyAdded:
{
Release::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
params.setSortMethod(ReleaseSortMethod::LastWritten);
params.setRange(range);
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
releases = Release::findIds(LmsApp->getDbSession(), params);
}
break;
}
case Mode::Search:
{ {
Release::FindParameters params; Release::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords()); params.setKeywords(getSearchKeywords());
params.setSortMethod(ReleaseSortMethod::LastWritten);
params.setRange(range); params.setRange(range);
{ {
@@ -118,6 +107,7 @@ namespace lms::ui
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setSortMethod(ReleaseSortMethod::Name); params.setSortMethod(ReleaseSortMethod::Name);
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
{ {
@@ -143,6 +133,7 @@ namespace lms::ui
Release::FindParameters params; Release::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setSortMethod(ReleaseSortMethod::Random); params.setSortMethod(ReleaseSortMethod::Random);
params.setRange(Range{ 0, getMaxCount() }); params.setRange(Range{ 0, getMaxCount() });
+14
View File
@@ -19,6 +19,7 @@
#include "ReleasesView.hpp" #include "ReleasesView.hpp"
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h> #include <Wt/WPushButton.h>
#include "database/Release.hpp" #include "database/Release.hpp"
@@ -44,6 +45,13 @@ namespace lms::ui
addFunction("tr", &Wt::WTemplate::Functions::tr); addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("id", &Wt::WTemplate::Functions::id); addFunction("id", &Wt::WTemplate::Functions::id);
Wt::WLineEdit* searEdit{ bindNew<Wt::WLineEdit>("search") };
searEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
searEdit->textInput().connect([this, searEdit]
{
refreshView(searEdit->text());
});
SortModeSelector* sortMode{ bindNew<SortModeSelector>("sort-mode", _defaultMode) }; SortModeSelector* sortMode{ bindNew<SortModeSelector>("sort-mode", _defaultMode) };
sortMode->sortModeChanged.connect([this](ReleaseCollector::Mode sortMode) sortMode->sortModeChanged.connect([this](ReleaseCollector::Mode sortMode)
{ {
@@ -98,6 +106,12 @@ namespace lms::ui
refreshView(); refreshView();
} }
void Releases::refreshView(const Wt::WString& searchText)
{
_releaseCollector.setSearch(searchText.toUTF8());
refreshView();
}
void Releases::addSome() void Releases::addSome()
{ {
const auto releaseIds{ _releaseCollector.get(Range {static_cast<std::size_t>(_container->getCount()), _batchSize}) }; const auto releaseIds{ _releaseCollector.get(Range {static_cast<std::size_t>(_container->getCount()), _batchSize}) };
+1
View File
@@ -38,6 +38,7 @@ namespace lms::ui
private: private:
void refreshView(); void refreshView();
void refreshView(ReleaseCollector::Mode mode); void refreshView(ReleaseCollector::Mode mode);
void refreshView(const Wt::WString& searchText);
void addSome(); void addSome();
std::vector<db::ReleaseId> getAllReleases(); std::vector<db::ReleaseId> getAllReleases();
-200
View File
@@ -1,200 +0,0 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SearchView.hpp"
#include <Wt/WPushButton.h>
#include "database/Artist.hpp"
#include "database/Release.hpp"
#include "database/Session.hpp"
#include "database/Track.hpp"
#include "common/InfiniteScrollingContainer.hpp"
#include "ArtistListHelpers.hpp"
#include "Filters.hpp"
#include "LmsApplication.hpp"
#include "ReleaseHelpers.hpp"
#include "TrackArtistLinkTypeSelector.hpp"
#include "TrackListHelpers.hpp"
namespace lms::ui
{
using namespace db;
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) }
{
addFunction("tr", &Wt::WTemplate::Functions::tr);
_stack = bindNew<Wt::WStackedWidget>("results");
_stack->setOverflow(Wt::Overflow::Visible); // wt makes it hidden by default
// 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")) };
TrackArtistLinkTypeSelector* linkTypeSelector{ artistResults->bindNew<TrackArtistLinkTypeSelector>("link-type", std::nullopt)};
linkTypeSelector->linkTypeChanged.connect([this](std::optional<TrackArtistLinkType> linkType)
{
refreshView(linkType);
});
_artists = artistResults->bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container"));
_artists->onRequestElements.connect([this] { addSomeArtists(); });
}
// 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([this, menuItem, index]
{
_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([this]
{
refreshView();
});
}
std::size_t SearchView::getBatchSize(Mode mode) const
{
auto it{ _batchSizes.find(mode) };
assert(it != _batchSizes.cend());
return it->second;
}
std::size_t SearchView::getMaxCount(Mode mode) const
{
auto it{ _maxCounts.find(mode) };
assert(it != _maxCounts.cend());
return it->second;
}
void SearchView::refreshView(std::optional<TrackArtistLinkType> linkType)
{
_artistCollector.setArtistLinkType(linkType);
refreshView();
}
void SearchView::refreshView(const Wt::WString& searchText)
{
_releaseCollector.setSearch(searchText.toUTF8());
_artistCollector.setSearch(searchText.toUTF8());
_trackCollector.setSearch(searchText.toUTF8());
refreshView();
}
void SearchView::refreshView()
{
_artists->reset();
_releases->reset();
_tracks->reset();
}
void SearchView::addSomeArtists()
{
using namespace db;
const Range range{ _artists->getCount(), getBatchSize(Mode::Artist) };
const RangeResults<ArtistId> artistIds{ _artistCollector.get(range) };
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
for (const ArtistId artistId : artistIds.results)
{
const Artist::pointer artist{ Artist::find(LmsApp->getDbSession(), artistId) };
if (artist)
_artists->add(ArtistListHelpers::createEntry(artist));
}
}
_artists->setHasMore(artistIds.moreResults);
}
void SearchView::addSomeReleases()
{
using namespace db;
const Range range{ _releases->getCount(), getBatchSize(Mode::Release) };
const RangeResults<ReleaseId> releaseIds{ _releaseCollector.get(range) };
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
for (const ReleaseId releaseId : releaseIds.results)
{
const Release::pointer release{ Release::find(LmsApp->getDbSession(), releaseId) };
if (release)
_releases->add(releaseListHelpers::createEntry(release));
}
}
_releases->setHasMore(releaseIds.moreResults);
}
void SearchView::addSomeTracks()
{
using namespace db;
const Range range{ _tracks->getCount(), getBatchSize(Mode::Track) };
const RangeResults<TrackId> trackIds{ _trackCollector.get(range) };
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
for (const TrackId trackId : trackIds.results)
{
const Track::pointer track{ Track::find(LmsApp->getDbSession(), trackId) };
if (track)
_tracks->add(TrackListHelpers::createEntry(track, _playQueueController, _filters));
}
}
_tracks->setHasMore(trackIds.moreResults);
}
}
-91
View File
@@ -1,91 +0,0 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <optional>
#include <unordered_map>
#include <Wt/WComboBox.h>
#include <Wt/WStackedWidget.h>
#include <Wt/WTemplate.h>
#include "database/Types.hpp"
#include "ArtistCollector.hpp"
#include "ReleaseCollector.hpp"
#include "TrackCollector.hpp"
namespace lms::ui
{
class InfiniteScrollingContainer;
class Filters;
class PlayQueueController;
class SearchView : public Wt::WTemplate
{
public:
SearchView(Filters& filters, PlayQueueController& playQueueController);
void refreshView(const Wt::WString& searchText);
private:
// same order as in the menu
enum class Mode
{
Artist,
Release,
Track,
};
static constexpr Mode _defaultMode{ Mode::Release };
static inline std::unordered_map<Mode, std::size_t> _batchSizes
{
{Mode::Artist, 6},
{Mode::Release, 6},
{Mode::Track, 6},
};
static inline std::unordered_map<Mode, std::size_t> _maxCounts
{
{Mode::Artist, 1000},
{Mode::Release, 504},
{Mode::Track, 500},
};
std::size_t getBatchSize(Mode mode) const;
std::size_t getMaxCount(Mode mode) const;
void refreshView();
void refreshView(std::optional<db::TrackArtistLinkType> linkType);
void addSomeArtists();
void addSomeReleases();
void addSomeTracks();
PlayQueueController& _playQueueController;
Filters& _filters;
ArtistCollector _artistCollector;
ReleaseCollector _releaseCollector;
TrackCollector _trackCollector;
Wt::WStackedWidget* _stack{};
Wt::WWidget* _currentActiveItem {};
InfiniteScrollingContainer* _artists{};
InfiniteScrollingContainer* _releases{};
InfiniteScrollingContainer* _tracks{};
};
} // namespace lms::ui
+6 -15
View File
@@ -55,6 +55,7 @@ namespace lms::ui
feedback::IFeedbackService::FindParameters params; feedback::IFeedbackService::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
tracks = feedbackService.findStarredTracks(params); tracks = feedbackService.findStarredTracks(params);
@@ -67,6 +68,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
tracks = scrobblingService.getRecentTracks(params); tracks = scrobblingService.getRecentTracks(params);
@@ -79,6 +81,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId()); params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
tracks = scrobblingService.getTopTracks(params); tracks = scrobblingService.getTopTracks(params);
@@ -86,26 +89,12 @@ namespace lms::ui
} }
case Mode::RecentlyAdded: case Mode::RecentlyAdded:
{
Track::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
params.setSortMethod(TrackSortMethod::LastWritten);
params.setRange(range);
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
tracks = Track::findIds(LmsApp->getDbSession(), params);
}
break;
}
case Mode::Search:
{ {
Track::FindParameters params; Track::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords()); params.setKeywords(getSearchKeywords());
params.setSortMethod(TrackSortMethod::LastWritten);
params.setRange(range); params.setRange(range);
{ {
@@ -120,6 +109,7 @@ namespace lms::ui
Track::FindParameters params; Track::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setRange(range); params.setRange(range);
{ {
@@ -145,6 +135,7 @@ namespace lms::ui
Track::FindParameters params; Track::FindParameters params;
params.setClusters(getFilters().getClusters()); params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary()); params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
params.setSortMethod(TrackSortMethod::Random); params.setSortMethod(TrackSortMethod::Random);
params.setRange(Range{ 0, getMaxCount() }); params.setRange(Range{ 0, getMaxCount() });
+14
View File
@@ -19,6 +19,7 @@
#include "TracksView.hpp" #include "TracksView.hpp"
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h> #include <Wt/WPushButton.h>
#include "database/Session.hpp" #include "database/Session.hpp"
@@ -45,6 +46,13 @@ namespace lms::ui
addFunction("tr", &Wt::WTemplate::Functions::tr); addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("id", &Wt::WTemplate::Functions::id); addFunction("id", &Wt::WTemplate::Functions::id);
Wt::WLineEdit* searEdit{ bindNew<Wt::WLineEdit>("search") };
searEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
searEdit->textInput().connect([this, searEdit]
{
refreshView(searEdit->text());
});
SortModeSelector* sortMode{ bindNew<SortModeSelector>("sort-mode", _defaultMode) }; SortModeSelector* sortMode{ bindNew<SortModeSelector>("sort-mode", _defaultMode) };
sortMode->sortModeChanged.connect([this](TrackCollector::Mode mode) sortMode->sortModeChanged.connect([this](TrackCollector::Mode mode)
{ {
@@ -99,6 +107,12 @@ namespace lms::ui
refreshView(); refreshView();
} }
void Tracks::refreshView(const Wt::WString& searchText)
{
_trackCollector.setSearch(searchText.toUTF8());
refreshView();
}
void Tracks::addSome() void Tracks::addSome()
{ {
auto transaction{ LmsApp->getDbSession().createReadTransaction() }; auto transaction{ LmsApp->getDbSession().createReadTransaction() };
+1
View File
@@ -38,6 +38,7 @@ namespace lms::ui
private: private:
void refreshView(); void refreshView();
void refreshView(TrackCollector::Mode mode); void refreshView(TrackCollector::Mode mode);
void refreshView(const Wt::WString& searchText);
void addSome(); void addSome();
std::vector<db::TrackId> getAllTracks(); std::vector<db::TrackId> getAllTracks();