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"