-
+
${play-btn class="btn btn-primary"}
- ${sort-mode}
+
+ ${search class="form-control me-1" type="search"}
+ ${sort-mode}
+
${releases}
diff --git a/approot/search.xml b/approot/search.xml
deleted file mode 100644
index 25709a2d..00000000
--- a/approot/search.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
- -
- ${releases class="nav-link"}
-
- -
- ${artists class="nav-link"}
-
- -
- ${tracks class="nav-link"}
-
-
-
- ${results}
-
-
-
-
- ${link-type}
-
- ${artists}
-
-
-
diff --git a/approot/tracks.xml b/approot/tracks.xml
index 21a84f0c..e9adbe12 100644
--- a/approot/tracks.xml
+++ b/approot/tracks.xml
@@ -5,7 +5,7 @@
-
+
${play-btn class="btn btn-primary"}
- ${sort-mode}
+
+ ${search class="form-control me-1" type="search"}
+ ${sort-mode}
+
${tracks}
diff --git a/src/libs/database/impl/Listen.cpp b/src/libs/database/impl/Listen.cpp
index f53f6cdc..dc67f690 100644
--- a/src/libs/database/impl/Listen.cpp
+++ b/src/libs/database/impl/Listen.cpp
@@ -32,9 +32,8 @@ namespace lms::db
Wt::Dbo::Query
createArtistsQuery(Session& session, const Listen::ArtistStatsFindParameters& params)
{
auto query{ session.getDboSession()->query("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("listen l ON l.track_id = t.id") };
+ .join("listen l ON l.track_id = t_a_l.track_id") };
if (params.user.isValid())
query.where("l.user_id = ?").bind(params.user);
@@ -45,7 +44,10 @@ namespace lms::db
assert(!params.artist.isValid()); // poor check
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);
+ }
if (params.linkType)
query.where("t_a_l.type = ?").bind(*params.linkType);
@@ -69,6 +71,26 @@ namespace lms::db
query.where(oss.str());
}
+ if (!params.keywords.empty())
+ {
+ std::vector clauses;
+ std::vector 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;
}
@@ -114,6 +136,9 @@ namespace lms::db
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;
}
@@ -157,6 +182,9 @@ namespace lms::db
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;
}
}
diff --git a/src/libs/database/include/database/Listen.hpp b/src/libs/database/include/database/Listen.hpp
index bc4dbaa0..e4d41d69 100644
--- a/src/libs/database/include/database/Listen.hpp
+++ b/src/libs/database/include/database/Listen.hpp
@@ -70,6 +70,7 @@ namespace lms::db
UserId user;
std::optional backend;
std::vector clusters; // if non empty, entities that belong to these clusters
+ std::vector keywords; // if non empty, name must match all of these keywords
std::optional range;
ArtistId artist; // if set, matching this artist
MediaLibraryId library;
@@ -77,6 +78,7 @@ namespace lms::db
StatsFindParameters& setUser(UserId _user) { user = _user; return *this; }
StatsFindParameters& setScrobblingBackend(std::optional _backend) { backend = _backend; return *this; }
StatsFindParameters& setClusters(const std::vector& _clusters) { clusters = _clusters; return *this; }
+ StatsFindParameters& setKeywords(const std::vector& _keywords) { keywords = _keywords; return *this; }
StatsFindParameters& setRange(std::optional _range) { range = _range; return *this; }
StatsFindParameters& setArtist(ArtistId _artist) { artist = _artist; return *this; }
StatsFindParameters& setMediaLibrary(MediaLibraryId _library) { library = _library; return *this; }
diff --git a/src/libs/database/include/database/Release.hpp b/src/libs/database/include/database/Release.hpp
index 6bb91457..d2d3349c 100644
--- a/src/libs/database/include/database/Release.hpp
+++ b/src/libs/database/include/database/Release.hpp
@@ -92,8 +92,8 @@ namespace lms::db
UserId starringUser; // only releases starred by this user
std::optional feedbackBackend; // and for this backend
ArtistId artist; // only releases that involved this user
- core::EnumSet trackArtistLinkTypes; // and for these link types
- core::EnumSet excludedTrackArtistLinkTypes; // but not for these link types
+ core::EnumSet trackArtistLinkTypes; // and for these link types
+ core::EnumSet excludedTrackArtistLinkTypes; // but not for these link types
std::string releaseType; // If set, albums that has this release type
MediaLibraryId mediaLibrary; // If set, releases that has at least a track in this library
diff --git a/src/libs/services/feedback/impl/FeedbackService.cpp b/src/libs/services/feedback/impl/FeedbackService.cpp
index 5826ead9..a9279156 100644
--- a/src/libs/services/feedback/impl/FeedbackService.cpp
+++ b/src/libs/services/feedback/impl/FeedbackService.cpp
@@ -96,6 +96,7 @@ namespace lms::feedback
Artist::FindParameters searchParams;
searchParams.setStarringUser(params.user, *backend);
searchParams.setClusters(params.clusters);
+ searchParams.setKeywords(params.keywords);
searchParams.setLinkType(params.linkType);
searchParams.setSortMethod(params.sortMethod);
searchParams.setRange(params.range);
@@ -136,6 +137,7 @@ namespace lms::feedback
Release::FindParameters searchParams;
searchParams.setStarringUser(params.user, *backend);
searchParams.setClusters(params.clusters);
+ searchParams.setKeywords(params.keywords);
searchParams.setSortMethod(ReleaseSortMethod::StarredDateDesc);
searchParams.setRange(params.range);
searchParams.setMediaLibrary(params.library);
@@ -175,6 +177,7 @@ namespace lms::feedback
Track::FindParameters searchParams;
searchParams.setStarringUser(params.user, *backend);
searchParams.setClusters(params.clusters);
+ searchParams.setKeywords(params.keywords);
searchParams.setSortMethod(TrackSortMethod::StarredDateDesc);
searchParams.setRange(params.range);
searchParams.setMediaLibrary(params.library);
diff --git a/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp b/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp
index 0f39cdb2..208ba1d1 100644
--- a/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp
+++ b/src/libs/services/feedback/include/services/feedback/IFeedbackService.hpp
@@ -54,11 +54,13 @@ namespace lms::feedback
{
db::UserId user;
std::vector clusters; // if non empty, at least one artist that belongs to these clusters
+ std::vector keywords; // if non empty, name must match all of these keywords
std::optional range;
db::MediaLibraryId library;
FindParameters& setUser(const db::UserId _user) { user = _user; return *this; }
FindParameters& setClusters(std::span _clusters) { clusters.assign(std::cbegin(_clusters), std::cend(_clusters)); return *this; }
+ FindParameters& setKeywords(const std::vector& _keywords) { keywords = _keywords; return *this; }
FindParameters& setRange(std::optional _range) { range = _range; return *this; }
FindParameters& setMediaLibrary(db::MediaLibraryId _library) { library = _library; return *this; }
};
diff --git a/src/libs/services/scrobbling/impl/ScrobblingService.cpp b/src/libs/services/scrobbling/impl/ScrobblingService.cpp
index f72b90ed..6b572efa 100644
--- a/src/libs/services/scrobbling/impl/ScrobblingService.cpp
+++ b/src/libs/services/scrobbling/impl/ScrobblingService.cpp
@@ -42,6 +42,7 @@ namespace lms::scrobbling
db::Listen::StatsFindParameters listenFindParams;
listenFindParams.setUser(params.user);
listenFindParams.setClusters(params.clusters);
+ listenFindParams.setKeywords(params.keywords);
listenFindParams.setRange(params.range);
listenFindParams.setMediaLibrary(params.library);
listenFindParams.setArtist(params.artist);
diff --git a/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp b/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp
index 2b73770e..7f04ca3e 100644
--- a/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp
+++ b/src/libs/services/scrobbling/include/services/scrobbling/IScrobblingService.hpp
@@ -59,14 +59,16 @@ namespace lms::scrobbling
struct FindParameters
{
- db::UserId user;
- std::vector clusters; // if non empty, at least one artist that belongs to these clusters
- std::optional range;
- db::MediaLibraryId library; // if set, match this library
- db::ArtistId artist; // if set, match this artist
+ db::UserId user;
+ std::vector clusters; // if non empty, at least one artist that belongs to these clusters
+ std::vector keywords; // if non empty, name must match all of these keywords
+ std::optional range;
+ db::MediaLibraryId library; // if set, match this library
+ db::ArtistId artist; // if set, match this artist
FindParameters& setUser(const db::UserId _user) { user = _user; return *this; }
FindParameters& setClusters(std::span _clusters) { clusters.assign(std::cbegin(_clusters), std::cend(_clusters)); return *this; }
+ FindParameters& setKeywords(const std::vector& _keywords) { keywords = _keywords; return *this; }
FindParameters& setRange(std::optional _range) { range = _range; return *this; }
FindParameters& setMediaLibrary(db::MediaLibraryId _library) { library = _library; return *this; }
FindParameters& setArtist(db::ArtistId _artist) { artist = _artist; return *this; }
diff --git a/src/lms/CMakeLists.txt b/src/lms/CMakeLists.txt
index 03f00b0e..c3ec3564 100644
--- a/src/lms/CMakeLists.txt
+++ b/src/lms/CMakeLists.txt
@@ -42,7 +42,6 @@ add_executable(lms
ui/explore/ReleasesView.cpp
ui/explore/ReleaseView.cpp
ui/explore/ReleaseTypes.cpp
- ui/explore/SearchView.cpp
ui/explore/SortModeSelector.cpp
ui/explore/TrackArtistLinkTypeSelector.cpp
ui/explore/TrackCollector.cpp
diff --git a/src/lms/ui/LmsApplication.cpp b/src/lms/ui/LmsApplication.cpp
index 0d06d730..4382f9c6 100644
--- a/src/lms/ui/LmsApplication.cpp
+++ b/src/lms/ui/LmsApplication.cpp
@@ -97,7 +97,6 @@ namespace lms::ui
res->use(appRoot + "playqueue");
res->use(appRoot + "release");
res->use(appRoot + "releases");
- res->use(appRoot + "search");
res->use(appRoot + "settings");
res->use(appRoot + "tracklist");
res->use(appRoot + "tracklists");
@@ -139,7 +138,6 @@ namespace lms::ui
{ "/artist", IdxExplore, false, std::nullopt },
{ "/releases", IdxExplore, false, Wt::WString::tr("Lms.Explore.releases") },
{ "/release", IdxExplore, false, std::nullopt },
- { "/search", IdxExplore, false, Wt::WString::tr("Lms.Explore.search") },
{ "/tracks", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracks") },
{ "/tracklists", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracklists") },
{ "/tracklist", IdxExplore, false, std::nullopt },
@@ -435,9 +433,6 @@ namespace lms::ui
logout->clicked().connect(this, &LmsApplication::logoutUser);
}
- Wt::WLineEdit* searchEdit{ navbar->bindNew("search") };
- searchEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
-
if (LmsApp->getUserType() == db::UserType::ADMIN)
{
navbar->setCondition("if-is-admin", true);
@@ -462,17 +457,6 @@ namespace lms::ui
_playQueue = mainStack->addWidget(std::move(playQueue));
mainStack->addNew();
- searchEdit->enterPressed().connect([this]
- {
- setInternalPath("/search", true);
- });
-
- searchEdit->textInput().connect([this, explore, searchEdit]
- {
- setInternalPath("/search", true);
- explore->search(searchEdit->text());
- });
-
// Admin stuff
if (getUserType() == db::UserType::ADMIN)
{
diff --git a/src/lms/ui/explore/ArtistCollector.cpp b/src/lms/ui/explore/ArtistCollector.cpp
index 097b63a3..098ffa49 100644
--- a/src/lms/ui/explore/ArtistCollector.cpp
+++ b/src/lms/ui/explore/ArtistCollector.cpp
@@ -54,6 +54,7 @@ namespace lms::ui
feedback::IFeedbackService::ArtistFindParameters params;
params.setUser(LmsApp->getUserId());
params.setClusters(filters.getClusters());
+ params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::StarredDateDesc);
@@ -67,6 +68,7 @@ namespace lms::ui
scrobbling::IScrobblingService::ArtistFindParameters params;
params.setUser(LmsApp->getUserId());
params.setClusters(filters.getClusters());
+ params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType);
params.setRange(range);
@@ -80,6 +82,7 @@ namespace lms::ui
scrobbling::IScrobblingService::ArtistFindParameters params;
params.setUser(LmsApp->getUserId());
params.setClusters(filters.getClusters());
+ params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType);
params.setRange(range);
@@ -92,6 +95,7 @@ namespace lms::ui
{
Artist::FindParameters params;
params.setClusters(filters.getClusters());
+ params.setKeywords(getSearchKeywords());
params.setMediaLibrary(filters.getMediaLibrary());
params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::LastWritten);
@@ -104,27 +108,12 @@ namespace lms::ui
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:
{
Artist::FindParameters params;
params.setClusters(filters.getClusters());
params.setMediaLibrary(filters.getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::SortName);
params.setRange(range);
@@ -152,6 +141,7 @@ namespace lms::ui
Artist::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::Random);
params.setRange(Range{ 0, getMaxCount() });
diff --git a/src/lms/ui/explore/ArtistsView.cpp b/src/lms/ui/explore/ArtistsView.cpp
index 9c0197b1..9437b2e5 100644
--- a/src/lms/ui/explore/ArtistsView.cpp
+++ b/src/lms/ui/explore/ArtistsView.cpp
@@ -38,10 +38,18 @@ namespace lms::ui
using namespace db;
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 }
{
addFunction("tr", &Wt::WTemplate::Functions::tr);
+ addFunction("id", &Wt::WTemplate::Functions::id);
+
+ Wt::WLineEdit* searEdit{ bindNew("search") };
+ searEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
+ searEdit->textInput().connect([this, searEdit]
+ {
+ refreshView(searEdit->text());
+ });
SortModeSelector* sortModeSelector{ bindNew("sort-mode", _defaultSortMode) };
sortModeSelector->sortModeChanged.connect([this](ArtistCollector::Mode sortMode)
@@ -87,6 +95,12 @@ namespace lms::ui
refreshView();
}
+ void Artists::refreshView(const Wt::WString& searchText)
+ {
+ _artistCollector.setSearch(searchText.toUTF8());
+ refreshView();
+ }
+
void Artists::addSome()
{
const auto artistIds{ _artistCollector.get(Range {static_cast(_container->getCount()), _batchSize}) };
diff --git a/src/lms/ui/explore/ArtistsView.hpp b/src/lms/ui/explore/ArtistsView.hpp
index 71bf44ee..95d8fc60 100644
--- a/src/lms/ui/explore/ArtistsView.hpp
+++ b/src/lms/ui/explore/ArtistsView.hpp
@@ -26,6 +26,7 @@
#include
#include "database/Types.hpp"
+#include "common/Template.hpp"
#include "ArtistCollector.hpp"
namespace lms::ui
@@ -33,7 +34,7 @@ namespace lms::ui
class Filters;
class InfiniteScrollingContainer;
- class Artists : public Wt::WTemplate
+ class Artists : public Template
{
public:
Artists(Filters& filters);
@@ -42,6 +43,7 @@ namespace lms::ui
void refreshView();
void refreshView(ArtistCollector::Mode mode);
void refreshView(std::optional linkType);
+ void refreshView(const Wt::WString& searchText);
void addSome();
static constexpr std::size_t _batchSize{ 30 };
diff --git a/src/lms/ui/explore/DatabaseCollectorBase.cpp b/src/lms/ui/explore/DatabaseCollectorBase.cpp
index ae1d7e7d..601ff01d 100644
--- a/src/lms/ui/explore/DatabaseCollectorBase.cpp
+++ b/src/lms/ui/explore/DatabaseCollectorBase.cpp
@@ -59,7 +59,10 @@ namespace lms::ui
void DatabaseCollectorBase::setSearch(std::string_view searchText)
{
_searchText = searchText;
- _searchKeywords = core::stringUtils::splitString(_searchText, ' ');
+ if (!searchText.empty())
+ _searchKeywords = core::stringUtils::splitString(_searchText, ' ');
+ else
+ _searchKeywords.clear();
}
} // ns UserInterface
diff --git a/src/lms/ui/explore/DatabaseCollectorBase.hpp b/src/lms/ui/explore/DatabaseCollectorBase.hpp
index dddd039e..63bfe960 100644
--- a/src/lms/ui/explore/DatabaseCollectorBase.hpp
+++ b/src/lms/ui/explore/DatabaseCollectorBase.hpp
@@ -45,7 +45,6 @@ namespace lms::ui
RecentlyPlayed,
RecentlyAdded,
MostPlayed,
- Search,
All
};
diff --git a/src/lms/ui/explore/Explore.cpp b/src/lms/ui/explore/Explore.cpp
index bae923fc..b1daf755 100644
--- a/src/lms/ui/explore/Explore.cpp
+++ b/src/lms/ui/explore/Explore.cpp
@@ -27,7 +27,6 @@
#include "Filters.hpp"
#include "ReleasesView.hpp"
#include "ReleaseView.hpp"
-#include "SearchView.hpp"
#include "TrackListView.hpp"
#include "TrackListsView.hpp"
#include "TracksView.hpp"
@@ -46,7 +45,6 @@ namespace lms::ui
IdxTrackList,
IdxReleases,
IdxRelease,
- IdxSearch,
IdxTracks,
};
@@ -58,7 +56,6 @@ namespace lms::ui
{ "/tracklist", IdxTrackList },
{ "/releases", IdxReleases },
{ "/release", IdxRelease },
- { "/search", IdxSearch },
{ "/tracks", IdxTracks },
};
@@ -103,10 +100,6 @@ namespace lms::ui
auto release = std::make_unique(filters, _playQueueController);
contentsStack->addWidget(std::move(release));
- auto search = std::make_unique(filters, _playQueueController);
- _search = search.get();
- contentsStack->addWidget(std::move(search));
-
auto tracks = std::make_unique(filters, _playQueueController);
contentsStack->addWidget(std::move(tracks));
@@ -117,9 +110,4 @@ namespace lms::ui
handleContentsPathChange(contentsStack);
}
-
- void Explore::search(const Wt::WString& searchText)
- {
- _search->refreshView(searchText);
- }
} // namespace lms::ui
diff --git a/src/lms/ui/explore/Explore.hpp b/src/lms/ui/explore/Explore.hpp
index ced70b41..48163c3c 100644
--- a/src/lms/ui/explore/Explore.hpp
+++ b/src/lms/ui/explore/Explore.hpp
@@ -34,7 +34,6 @@ namespace lms::ui
public:
Explore(Filters& filters, PlayQueue& playQueue);
- void search(const Wt::WString& searchText);
PlayQueueController& getPlayQueueController() { return _playQueueController; }
private:
diff --git a/src/lms/ui/explore/ReleaseCollector.cpp b/src/lms/ui/explore/ReleaseCollector.cpp
index 98f37025..b166b9e5 100644
--- a/src/lms/ui/explore/ReleaseCollector.cpp
+++ b/src/lms/ui/explore/ReleaseCollector.cpp
@@ -53,6 +53,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
releases = feedbackService.findStarredReleases(params);
break;
@@ -64,6 +65,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
releases = scrobblingService.getRecentReleases(params);
@@ -76,6 +78,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
releases = scrobblingService.getTopReleases(params);
@@ -83,26 +86,12 @@ namespace lms::ui
}
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;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
+ params.setSortMethod(ReleaseSortMethod::LastWritten);
params.setRange(range);
{
@@ -118,6 +107,7 @@ namespace lms::ui
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
params.setSortMethod(ReleaseSortMethod::Name);
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
{
@@ -143,6 +133,7 @@ namespace lms::ui
Release::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setSortMethod(ReleaseSortMethod::Random);
params.setRange(Range{ 0, getMaxCount() });
diff --git a/src/lms/ui/explore/ReleasesView.cpp b/src/lms/ui/explore/ReleasesView.cpp
index 592e7588..088de9a2 100644
--- a/src/lms/ui/explore/ReleasesView.cpp
+++ b/src/lms/ui/explore/ReleasesView.cpp
@@ -19,6 +19,7 @@
#include "ReleasesView.hpp"
+#include
#include
#include "database/Release.hpp"
@@ -44,6 +45,13 @@ namespace lms::ui
addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("id", &Wt::WTemplate::Functions::id);
+ Wt::WLineEdit* searEdit{ bindNew("search") };
+ searEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
+ searEdit->textInput().connect([this, searEdit]
+ {
+ refreshView(searEdit->text());
+ });
+
SortModeSelector* sortMode{ bindNew("sort-mode", _defaultMode) };
sortMode->sortModeChanged.connect([this](ReleaseCollector::Mode sortMode)
{
@@ -98,6 +106,12 @@ namespace lms::ui
refreshView();
}
+ void Releases::refreshView(const Wt::WString& searchText)
+ {
+ _releaseCollector.setSearch(searchText.toUTF8());
+ refreshView();
+ }
+
void Releases::addSome()
{
const auto releaseIds{ _releaseCollector.get(Range {static_cast(_container->getCount()), _batchSize}) };
diff --git a/src/lms/ui/explore/ReleasesView.hpp b/src/lms/ui/explore/ReleasesView.hpp
index 555db842..85cd531d 100644
--- a/src/lms/ui/explore/ReleasesView.hpp
+++ b/src/lms/ui/explore/ReleasesView.hpp
@@ -38,6 +38,7 @@ namespace lms::ui
private:
void refreshView();
void refreshView(ReleaseCollector::Mode mode);
+ void refreshView(const Wt::WString& searchText);
void addSome();
std::vector getAllReleases();
diff --git a/src/lms/ui/explore/SearchView.cpp b/src/lms/ui/explore/SearchView.cpp
deleted file mode 100644
index 508c4322..00000000
--- a/src/lms/ui/explore/SearchView.cpp
+++ /dev/null
@@ -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 .
- */
-
-#include "SearchView.hpp"
-
-#include
-
-#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("results");
- _stack->setOverflow(Wt::Overflow::Visible); // wt makes it hidden by default
-
- // releases
- _releases = _stack->addNew(Wt::WString::tr("Lms.Explore.Releases.template.container"));
- _releases->onRequestElements.connect([this] { addSomeReleases(); });
-
- // artists
- {
- Wt::WTemplate* artistResults{ _stack->addNew(Wt::WString::tr("Lms.Explore.Search.template.artists")) };
-
- TrackArtistLinkTypeSelector* linkTypeSelector{ artistResults->bindNew("link-type", std::nullopt)};
- linkTypeSelector->linkTypeChanged.connect([this](std::optional linkType)
- {
- refreshView(linkType);
- });
-
- _artists = artistResults->bindNew("artists", Wt::WString::tr("Lms.Explore.Artists.template.container"));
- _artists->onRequestElements.connect([this] { addSomeArtists(); });
- }
-
- // Tracks
- _tracks = _stack->addNew();
- _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(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 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 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 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 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);
- }
-}
\ No newline at end of file
diff --git a/src/lms/ui/explore/SearchView.hpp b/src/lms/ui/explore/SearchView.hpp
deleted file mode 100644
index 5a44e3b9..00000000
--- a/src/lms/ui/explore/SearchView.hpp
+++ /dev/null
@@ -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 .
- */
-
-#pragma once
-
-#include
-#include
-
-#include
-#include
-#include
-
-#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 _batchSizes
- {
- {Mode::Artist, 6},
- {Mode::Release, 6},
- {Mode::Track, 6},
- };
- static inline std::unordered_map _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 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
-
diff --git a/src/lms/ui/explore/TrackCollector.cpp b/src/lms/ui/explore/TrackCollector.cpp
index b54d5a5a..7b4a6947 100644
--- a/src/lms/ui/explore/TrackCollector.cpp
+++ b/src/lms/ui/explore/TrackCollector.cpp
@@ -55,6 +55,7 @@ namespace lms::ui
feedback::IFeedbackService::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
params.setUser(LmsApp->getUserId());
tracks = feedbackService.findStarredTracks(params);
@@ -67,6 +68,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
tracks = scrobblingService.getRecentTracks(params);
@@ -79,6 +81,7 @@ namespace lms::ui
params.setUser(LmsApp->getUserId());
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
tracks = scrobblingService.getTopTracks(params);
@@ -86,26 +89,12 @@ namespace lms::ui
}
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;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
params.setKeywords(getSearchKeywords());
+ params.setSortMethod(TrackSortMethod::LastWritten);
params.setRange(range);
{
@@ -120,6 +109,7 @@ namespace lms::ui
Track::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setRange(range);
{
@@ -145,6 +135,7 @@ namespace lms::ui
Track::FindParameters params;
params.setClusters(getFilters().getClusters());
params.setMediaLibrary(getFilters().getMediaLibrary());
+ params.setKeywords(getSearchKeywords());
params.setSortMethod(TrackSortMethod::Random);
params.setRange(Range{ 0, getMaxCount() });
diff --git a/src/lms/ui/explore/TracksView.cpp b/src/lms/ui/explore/TracksView.cpp
index 018f5d42..4d9bdba1 100644
--- a/src/lms/ui/explore/TracksView.cpp
+++ b/src/lms/ui/explore/TracksView.cpp
@@ -19,6 +19,7 @@
#include "TracksView.hpp"
+#include
#include
#include "database/Session.hpp"
@@ -45,6 +46,13 @@ namespace lms::ui
addFunction("tr", &Wt::WTemplate::Functions::tr);
addFunction("id", &Wt::WTemplate::Functions::id);
+ Wt::WLineEdit* searEdit{ bindNew("search") };
+ searEdit->setPlaceholderText(Wt::WString::tr("Lms.Explore.Search.search-placeholder"));
+ searEdit->textInput().connect([this, searEdit]
+ {
+ refreshView(searEdit->text());
+ });
+
SortModeSelector* sortMode{ bindNew("sort-mode", _defaultMode) };
sortMode->sortModeChanged.connect([this](TrackCollector::Mode mode)
{
@@ -99,6 +107,12 @@ namespace lms::ui
refreshView();
}
+ void Tracks::refreshView(const Wt::WString& searchText)
+ {
+ _trackCollector.setSearch(searchText.toUTF8());
+ refreshView();
+ }
+
void Tracks::addSome()
{
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
diff --git a/src/lms/ui/explore/TracksView.hpp b/src/lms/ui/explore/TracksView.hpp
index 748467b0..7f479195 100644
--- a/src/lms/ui/explore/TracksView.hpp
+++ b/src/lms/ui/explore/TracksView.hpp
@@ -38,6 +38,7 @@ namespace lms::ui
private:
void refreshView();
void refreshView(TrackCollector::Mode mode);
+ void refreshView(const Wt::WString& searchText);
void addSome();
std::vector getAllTracks();