diff --git a/Makefile.am b/Makefile.am
index 5737756e..bbc921d5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,7 @@ lms_approot_DATA = \
approot/login.xml \
approot/mediaplayer.xml \
approot/messages.xml \
+ approot/playhistory.xml \
approot/playqueue.xml \
approot/release.xml \
approot/releases.xml \
diff --git a/approot/messages.xml b/approot/messages.xml
index 561a2f49..5419428a 100644
--- a/approot/messages.xml
+++ b/approot/messages.xml
@@ -64,8 +64,8 @@
Add filter
Artists
-Most played artists
-Most played albums
+Top artists
+Top albums
Recently added artists
Recently added albums
Recently played artists
@@ -85,6 +85,10 @@
Play Queue
Radio mode
+
+Play History
+
+
Account
Audio
diff --git a/src/Makefile.am b/src/Makefile.am
index f0a622f3..468d413d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ lms_SOURCES = \
$(srcdir)/ui/LmsApplicationGroup.cpp \
$(srcdir)/ui/MediaPlayer.cpp \
$(srcdir)/ui/PlayQueueView.cpp \
+ $(srcdir)/ui/PlayHistoryView.cpp \
$(srcdir)/ui/SettingsView.cpp \
$(srcdir)/ui/admin/DatabaseSettingsView.cpp \
$(srcdir)/ui/admin/InitWizardView.cpp \
diff --git a/src/database/TrackList.cpp b/src/database/TrackList.cpp
index d46b4e58..d7983c57 100644
--- a/src/database/TrackList.cpp
+++ b/src/database/TrackList.cpp
@@ -102,6 +102,22 @@ TrackList::getEntries(int offset, int size) const
return std::vector>(entries.begin(), entries.end());
}
+std::vector>
+TrackList::getEntriesReverse(int offset, int size) const
+{
+ assert(session());
+ assert(IdIsValid(self()->id()));
+
+ Wt::Dbo::collection> entries =
+ session()->find()
+ .where("tracklist_id = ?").bind(self().id())
+ .orderBy("id DESC")
+ .limit(size)
+ .offset(offset);
+
+ return std::vector>(entries.begin(), entries.end());
+}
+
Wt::Dbo::ptr
TrackList::getEntry(std::size_t pos) const
{
diff --git a/src/database/TrackList.hpp b/src/database/TrackList.hpp
index 0a54a2c7..60637b9d 100644
--- a/src/database/TrackList.hpp
+++ b/src/database/TrackList.hpp
@@ -67,6 +67,7 @@ class TrackList : public Wt::Dbo::Dbo
std::size_t getCount() const;
Wt::Dbo::ptr getEntry(std::size_t pos) const;
std::vector> getEntries(int offset = -1, int size = -1) const;
+ std::vector> getEntriesReverse(int offset = -1, int size = -1) const;
std::vector getTrackIds() const;
diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp
index 8dc0e9f5..8488339a 100644
--- a/src/ui/LmsApplication.cpp
+++ b/src/ui/LmsApplication.cpp
@@ -36,6 +36,7 @@
#include "explore/Explore.hpp"
#include "MediaPlayer.hpp"
+#include "PlayHistoryView.hpp"
#include "PlayQueueView.hpp"
#include "SettingsView.hpp"
@@ -99,6 +100,7 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
messageResourceBundle().use(appRoot() + "mediaplayer");
messageResourceBundle().use(appRoot() + "messages");
messageResourceBundle().use(appRoot() + "playqueue");
+ messageResourceBundle().use(appRoot() + "playhistory");
messageResourceBundle().use(appRoot() + "release");
messageResourceBundle().use(appRoot() + "releases");
messageResourceBundle().use(appRoot() + "settings");
@@ -209,6 +211,7 @@ enum IdxRoot
{
IdxExplore = 0,
IdxPlayQueue,
+ IdxPlayHistory,
IdxSettings,
IdxAdminDatabase,
IdxAdminUsers,
@@ -231,6 +234,7 @@ handlePathChange(Wt::WStackedWidget* stack, bool isAdmin)
{ "/release", IdxExplore, false },
{ "/tracks", IdxExplore, false },
{ "/playqueue", IdxPlayQueue, false },
+ { "/playhistory", IdxPlayHistory, false },
{ "/settings", IdxSettings, false },
{ "/admin/database", IdxAdminDatabase, true },
{ "/admin/users", IdxAdminUsers, true },
@@ -339,6 +343,11 @@ LmsApplication::createHome()
menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/playqueue"));
menuItem->setSelectable(false);
}
+ {
+ auto menuItem = menu->insertItem(4, Wt::WString::tr("Lms.PlayHistory.playhistory"));
+ menuItem->setLink(Wt::WLink(Wt::LinkType::InternalPath, "/playhistory"));
+ menuItem->setSelectable(false);
+ }
Wt::WMenu* rightMenu = navbar->addMenu(std::make_unique(), Wt::AlignmentFlag::Right);
std::size_t itemCounter = 0;
@@ -380,6 +389,7 @@ LmsApplication::createHome()
Explore* explore = mainStack->addNew();
PlayQueue* playqueue = mainStack->addNew();
+ PlayHistory* playhistory = mainStack->addNew();
mainStack->addNew();
// Admin stuff
@@ -419,12 +429,7 @@ LmsApplication::createHome()
});
// Events from the PlayQueue
- playqueue->playTrack.connect([=](Database::IdType trackId)
- {
- Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
-
- LmsApp->getUser()->getPlayedTrackList().modify()->add(trackId);
- });
+ playqueue->playTrack.connect(playhistory, &PlayHistory::addTrack);
playqueue->playTrack.connect(explore, &Explore::handleTrackPlayed);
playqueue->playTrack.connect(player, &MediaPlayer::playTrack);
diff --git a/src/ui/PlayHistoryView.cpp b/src/ui/PlayHistoryView.cpp
new file mode 100644
index 00000000..a6859b07
--- /dev/null
+++ b/src/ui/PlayHistoryView.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 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 "PlayHistoryView.hpp"
+
+#include
+#include
+
+#include "utils/Logger.hpp"
+
+#include "database/Track.hpp"
+#include "database/TrackList.hpp"
+
+#include "LmsApplication.hpp"
+
+namespace {
+
+using namespace UserInterface;
+
+std::unique_ptr createEntry(Database::Track::pointer track)
+{
+ auto entry = std::make_unique(Wt::WString::tr("Lms.PlayHistory.template.entry"));
+
+ entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
+
+ auto artist = track->getArtist();
+ if (artist)
+ {
+ entry->setCondition("if-has-artist", true);
+ entry->bindWidget("artist-name", LmsApplication::createArtistAnchor(track->getArtist()));
+ }
+ auto release = track->getRelease();
+ if (release)
+ {
+ entry->setCondition("if-has-release", true);
+ entry->bindWidget("release-name", LmsApplication::createReleaseAnchor(track->getRelease()));
+ }
+
+ return entry;
+}
+
+}
+
+namespace UserInterface {
+
+PlayHistory::PlayHistory()
+: Wt::WTemplate(Wt::WString::tr("Lms.PlayHistory.template"))
+{
+ addFunction("tr", &Wt::WTemplate::Functions::tr);
+
+ _entriesContainer = bindNew("entries");
+
+ // TODO move "Lms.Explore.show-more"
+ _showMore = bindNew("show-more", Wt::WString::tr("Lms.Explore.show-more"));
+ _showMore->addFunction("tr", &Wt::WTemplate::Functions::tr);
+ _showMore->setHidden(true);
+
+ _showMore->clicked().connect([=]
+ {
+ addSome();
+ });
+
+ addSome();
+}
+
+void
+PlayHistory::addTrack(Database::IdType trackId)
+{
+ Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
+
+ auto trackEntry = LmsApp->getUser()->getPlayedTrackList().modify()->add(trackId);
+ _entriesContainer->insertWidget(0, createEntry(trackEntry->getTrack()));
+}
+
+
+void
+PlayHistory::addSome()
+{
+ Wt::Dbo::Transaction transaction (LmsApp->getDboSession());
+
+ auto trackList = LmsApp->getUser()->getPlayedTrackList();
+ auto trackEntries = trackList->getEntriesReverse(_entriesContainer->count(), 50);
+ for (auto trackEntry : trackEntries)
+ _entriesContainer->addWidget(createEntry(trackEntry->getTrack()));
+
+ _showMore->setHidden(static_cast(_entriesContainer->count()) >= trackList->getCount());
+}
+
+} // namespace UserInterface
+
diff --git a/src/ui/PlayHistoryView.hpp b/src/ui/PlayHistoryView.hpp
new file mode 100644
index 00000000..5c2ee676
--- /dev/null
+++ b/src/ui/PlayHistoryView.hpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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 "database/Types.hpp"
+
+namespace UserInterface {
+
+class PlayHistory : public Wt::WTemplate
+{
+ public:
+ PlayHistory();
+
+ void addTrack(Database::IdType trackId);
+
+ private:
+
+ void addSome();
+
+ Wt::WContainerWidget* _entriesContainer;
+ Wt::WTemplate* _showMore;
+};
+
+} // namespace UserInterface
+
diff --git a/src/ui/PlayQueueView.cpp b/src/ui/PlayQueueView.cpp
index f0334ae0..ce3fc83b 100644
--- a/src/ui/PlayQueueView.cpp
+++ b/src/ui/PlayQueueView.cpp
@@ -22,8 +22,6 @@
#include
#include
-#include
-#include
#include
#include "utils/Logger.hpp"