From 98369c9219c0dbb68b33e310901fc66e3401e7fd Mon Sep 17 00:00:00 2001 From: emeric Date: Wed, 3 Jun 2026 22:30:45 +0200 Subject: [PATCH] Reuse path router for main view --- src/lms/ui/LmsApplication.cpp | 84 +++++++++----------------------- src/lms/ui/common/PathRouter.cpp | 6 +++ src/lms/ui/common/PathRouter.hpp | 9 +++- 3 files changed, 36 insertions(+), 63 deletions(-) diff --git a/src/lms/ui/LmsApplication.cpp b/src/lms/ui/LmsApplication.cpp index f78a99cc..62f9b1ed 100644 --- a/src/lms/ui/LmsApplication.cpp +++ b/src/lms/ui/LmsApplication.cpp @@ -56,6 +56,7 @@ #include "admin/About.hpp" #include "admin/AdminView.hpp" #include "admin/InitWizardView.hpp" +#include "common/PathRouter.hpp" #include "common/Template.hpp" #include "explore/Explore.hpp" #include "explore/Filters.hpp" @@ -128,55 +129,6 @@ namespace lms::ui return locale; } - enum IdxRoot - { - IdxExplore = 0, - IdxPlayQueue, - IdxSettings, - IdxAdmin, - }; - - void handlePathChange(Wt::WStackedWidget& stack, bool isAdmin) - { - static const struct - { - std::string path; - int index; - bool admin; - std::optional title; - } views[] = { - { "/artists", IdxExplore, false, Wt::WString::tr("Lms.Explore.artists") }, - { "/artist", IdxExplore, false, std::nullopt }, - { "/releases", IdxExplore, false, Wt::WString::tr("Lms.Explore.releases") }, - { "/release", IdxExplore, false, std::nullopt }, - { "/tracks", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracks") }, - { "/tracklists", IdxExplore, false, Wt::WString::tr("Lms.Explore.tracklists") }, - { "/tracklist", IdxExplore, false, std::nullopt }, - { "/playqueue", IdxPlayQueue, false, Wt::WString::tr("Lms.PlayQueue.playqueue") }, - { "/settings", IdxSettings, false, std::nullopt }, - { "/admin", IdxAdmin, true, std::nullopt }, - }; - - LMS_LOG(UI, DEBUG, "Internal path changed to '" << wApp->internalPath() << "'"); - - for (const auto& view : views) - { - if (wApp->internalPathMatches(view.path)) - { - if (view.admin && !isAdmin) - break; - - stack.setCurrentIndex(view.index); - if (view.title) - LmsApp->setTitle(*view.title); - - LmsApp->doJavaScript(LmsApp->javaScriptClass() + ".updateActiveNav('" + wApp->internalPath() + "')"); - return; - } - } - - wApp->setInternalPath(defaultPath, true); - } } // namespace std::unique_ptr LmsApplication::create(const Wt::WEnvironment& env, db::IDb& db, LmsApplicationManager& appManager, AuthenticationBackend authBackend) @@ -490,19 +442,22 @@ namespace lms::ui } } - // Contents - // Order is important in mainStack, see IdxRoot! - Wt::WStackedWidget* mainStack{ main->bindNew("contents") }; - mainStack->setOverflow(Wt::Overflow::Visible); // wt makes it hidden by default + PathRouter* mainRouter{ main->bindNew("contents") }; - std::unique_ptr playQueue{ std::make_unique() }; - Explore* explore{ mainStack->addNew(*filters, *playQueue) }; - _playQueue = mainStack->addWidget(std::move(playQueue)); - mainStack->addNew(); + _playQueue = mainRouter->add("/playqueue", Wt::WString::tr("Lms.PlayQueue.playqueue")); + + Explore* explore{ mainRouter->add("/artists", Wt::WString::tr("Lms.Explore.artists"), *filters, *_playQueue) }; + mainRouter->addRoute("/artist", std::nullopt, explore); + mainRouter->addRoute("/releases", Wt::WString::tr("Lms.Explore.releases"), explore); + mainRouter->addRoute("/release", std::nullopt, explore); + mainRouter->addRoute("/tracks", Wt::WString::tr("Lms.Explore.tracks"), explore); + mainRouter->addRoute("/tracklists", Wt::WString::tr("Lms.Explore.tracklists"), explore); + mainRouter->addRoute("/tracklist", std::nullopt, explore); + + mainRouter->add("/settings", std::nullopt); - // Admin stuff if (getUserType() == db::UserType::ADMIN) - mainStack->addNew(); + mainRouter->add("/admin", std::nullopt); explore->getPlayQueueController().setMaxTrackCountToEnqueue(_playQueue->getCapacity()); @@ -560,11 +515,16 @@ namespace lms::ui }); } - internalPathChanged().connect(mainStack, [=] { - handlePathChange(*mainStack, isAdmin); + internalPathChanged().connect([this] { + LMS_LOG(UI, DEBUG, "Internal path changed to '" << wApp->internalPath() << "'"); + doJavaScript(javaScriptClass() + ".updateActiveNav('" + wApp->internalPath() + "')"); }); - handlePathChange(*mainStack, isAdmin); + mainRouter->noMatch().connect([] { + wApp->setInternalPath(defaultPath, true); + }); + + mainRouter->activate(); } void LmsApplication::notify(const Wt::WEvent& event) diff --git a/src/lms/ui/common/PathRouter.cpp b/src/lms/ui/common/PathRouter.cpp index b4cb429c..263242ca 100644 --- a/src/lms/ui/common/PathRouter.cpp +++ b/src/lms/ui/common/PathRouter.cpp @@ -31,6 +31,11 @@ namespace lms::ui _stack->setOverflow(Wt::Overflow::Visible); } + void PathRouter::addRoute(std::string_view path, std::optional title, Wt::WWidget* widget) + { + _routes.emplace_back(Route{ std::string{ path }, widget, std::move(title) }); + } + void PathRouter::activate() { handlePathChange(); @@ -52,5 +57,6 @@ namespace lms::ui return; } } + _noMatchSignal.emit(); } } // namespace lms::ui diff --git a/src/lms/ui/common/PathRouter.hpp b/src/lms/ui/common/PathRouter.hpp index 53e887d6..542a28b0 100644 --- a/src/lms/ui/common/PathRouter.hpp +++ b/src/lms/ui/common/PathRouter.hpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -39,10 +40,15 @@ namespace lms::ui T* add(std::string_view path, std::optional title, Args&&... args) { T* widget{ _stack->addNew(std::forward(args)...) }; - _routes.emplace_back(Route{ std::string{ path }, widget, std::move(title) }); + addRoute(path, std::move(title), widget); return widget; } + void addRoute(std::string_view path, std::optional title, Wt::WWidget* widget); + + // Emitted when no registered route matches the current internal path. + Wt::Signal<>& noMatch() { return _noMatchSignal; } + // Call once after all routes are registered — performs initial routing and starts listening to path changes. void activate(); @@ -50,6 +56,7 @@ namespace lms::ui void handlePathChange(); Wt::WStackedWidget* _stack{}; + Wt::Signal<> _noMatchSignal; struct Route {