From 71b612f8052be18aac53061cf14dcb519d502130 Mon Sep 17 00:00:00 2001 From: Lukasz Mastalerz Date: Tue, 31 Oct 2023 15:54:19 +0100 Subject: [PATCH] [BH-1815] Optimalize loading music files in relaxation Relaxation is loading smooth with any number of files. --- harmony_changelog.md | 1 + module-db/Interface/MultimediaFilesRecord.cpp | 14 +- module-db/Interface/MultimediaFilesRecord.hpp | 5 +- .../QueryMultimediaFilesCount.cpp | 10 +- .../QueryMultimediaFilesCount.hpp | 11 +- .../ApplicationBellRelaxation.cpp | 12 +- .../CMakeLists.txt | 4 + .../model/RelaxationSongsModel.cpp | 75 ++++++++++ .../model/RelaxationSongsModel.hpp | 48 +++++++ .../model/RelaxationSongsRepository.cpp | 135 ++++++++++++++++++ .../model/RelaxationSongsRepository.hpp | 43 ++++++ .../RelaxationMainWindowPresenter.cpp | 38 +++-- .../RelaxationMainWindowPresenter.hpp | 18 ++- .../windows/RelaxationMainWindow.cpp | 59 ++++---- .../windows/RelaxationMainWindow.hpp | 9 +- .../RelaxationRunningProgressWindow.cpp | 1 - .../common/src/options/BellOptionWindow.cpp | 3 +- products/BellHybrid/paths/Paths.cpp | 2 +- products/BellHybrid/paths/Paths.hpp | 2 +- 19 files changed, 417 insertions(+), 73 deletions(-) create mode 100644 products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.cpp create mode 100644 products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.hpp create mode 100644 products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.cpp create mode 100644 products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.hpp diff --git a/harmony_changelog.md b/harmony_changelog.md index 6ace9536063696470e84b1d3c19a6acbd7f51d25..c637230e575c2a61adeff542b47f1992e337d7a4 100644 --- a/harmony_changelog.md +++ b/harmony_changelog.md @@ -24,6 +24,7 @@ ### Changed / Improved * Disabled USB MTP protocol +* Optimize the way Relaxation is loading music files ## [2.2.1 2023-10-30] diff --git a/module-db/Interface/MultimediaFilesRecord.cpp b/module-db/Interface/MultimediaFilesRecord.cpp index ff8771b5a1bf53536e43225fb99676054856e0d3..185330b64a69e107dfd6f45ba8822de2cc9b8f69 100644 --- a/module-db/Interface/MultimediaFilesRecord.cpp +++ b/module-db/Interface/MultimediaFilesRecord.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "MultimediaFilesRecord.hpp" @@ -81,6 +81,9 @@ namespace db::multimedia_files if (typeid(*query) == typeid(query::GetByPath)) { return runQueryImplGetByPath(std::static_pointer_cast(query)); } + if (typeid(*query) == typeid(query::GetCountForPath)) { + return runQueryImplGetCountForPath(std::static_pointer_cast(query)); + } return nullptr; } @@ -269,4 +272,13 @@ namespace db::multimedia_files response->setRequestQuery(query); return response; } + + std::unique_ptr MultimediaFilesRecordInterface:: + runQueryImplGetCountForPath(const std::shared_ptr &query) + { + const auto ret = database->files.count(std::vector{query->path}); + auto response = std::make_unique(ret); + response->setRequestQuery(query); + return response; + } } // namespace db::multimedia_files diff --git a/module-db/Interface/MultimediaFilesRecord.hpp b/module-db/Interface/MultimediaFilesRecord.hpp index b0d7ab2377c33a8254fd2d7499e411b488433987..58aca65fa8cf3d0d26bf23bbc16c2e5ab9a0f0fc 100644 --- a/module-db/Interface/MultimediaFilesRecord.hpp +++ b/module-db/Interface/MultimediaFilesRecord.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -44,6 +44,7 @@ namespace db::multimedia_files::query class RemoveAll; class RemoveByPath; class RemoveResult; + class GetCountForPath; } // namespace db::multimedia_files::query namespace db::multimedia_files @@ -99,6 +100,8 @@ namespace db::multimedia_files const std::shared_ptr &query); std::unique_ptr runQueryImplRemoveByPath( const std::shared_ptr &query); + std::unique_ptr runQueryImplGetCountForPath( + const std::shared_ptr &query); MultimediaFilesDB *database = nullptr; }; diff --git a/module-db/queries/multimedia_files/QueryMultimediaFilesCount.cpp b/module-db/queries/multimedia_files/QueryMultimediaFilesCount.cpp index e7f80ba70d9c5ca6ae1e9fae49ed8b7ee04fbee2..8de991d99c6b257e05039a8992e23f95113cf0c0 100644 --- a/module-db/queries/multimedia_files/QueryMultimediaFilesCount.cpp +++ b/module-db/queries/multimedia_files/QueryMultimediaFilesCount.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "QueryMultimediaFilesCount.hpp" @@ -61,4 +61,12 @@ namespace db::multimedia_files::query return "GetCountForAlbum"; } + GetCountForPath::GetCountForPath(const std::string &path) : Query(Query::Type::Read), path(path) + {} + + [[nodiscard]] auto GetCountForPath::debugInfo() const -> std::string + { + return "GetCountForPath"; + } + } // namespace db::multimedia_files::query diff --git a/module-db/queries/multimedia_files/QueryMultimediaFilesCount.hpp b/module-db/queries/multimedia_files/QueryMultimediaFilesCount.hpp index a7ddbfed823cd3ad681d54f3f419b3d0a81da0da..ac8820e6617c0c34ddfc159f0a576eb11c46cc22 100644 --- a/module-db/queries/multimedia_files/QueryMultimediaFilesCount.hpp +++ b/module-db/queries/multimedia_files/QueryMultimediaFilesCount.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -35,6 +35,15 @@ namespace db::multimedia_files::query const Album album; }; + class GetCountForPath : public Query + { + public: + explicit GetCountForPath(const std::string &path); + [[nodiscard]] auto debugInfo() const -> std::string override; + + const std::string path; + }; + class GetCountResult : public QueryResult { unsigned count; diff --git a/products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp b/products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp index 1dee2d52853342dc4af68d09ba7b258f27330913..5883dc4d0399650660a46fb03150bbc9f6248e0c 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp +++ b/products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp @@ -63,11 +63,13 @@ namespace app void ApplicationBellRelaxation::createUserInterface() { windowsFactory.attach(gui::name::window::main_window, [](ApplicationCommon *app, const std::string &name) { - auto tagsFetcher = std::make_unique(app); - const auto paths = std::vector{paths::audio::proprietary() / paths::audio::relaxation(), - paths::audio::userApp() / paths::audio::relaxation()}; - auto soundsRepository = std::make_unique(app, std::move(tagsFetcher), paths); - auto presenter = std::make_unique(std::move(soundsRepository)); + const auto paths = std::map{ + {relaxation::MusicType::Relaxation, paths::audio::proprietary() / paths::audio::relaxation()}, + {relaxation::MusicType::User, paths::audio::userApp() / paths::audio::relaxation()}}; + + auto soundsRepository = std::make_unique(app, paths); + auto songsModel = std::make_unique(app, std::move(soundsRepository)); + auto presenter = std::make_unique(std::move(songsModel)); return std::make_unique(app, std::move(presenter)); }); windowsFactory.attach( diff --git a/products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt b/products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt index 48593c825d68053e18d36887840fdfd467b83219..cc12d6e64d68db62bf7080c6cede49c485c820b9 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt +++ b/products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt @@ -58,6 +58,10 @@ target_sources(application-bell-relaxation windows/RelaxationEndedWindow.hpp windows/RelaxationLowBatteryWindow.hpp windows/RelaxationErrorWindow.hpp + model/RelaxationSongsModel.hpp + model/RelaxationSongsModel.cpp + model/RelaxationSongsRepository.hpp + model/RelaxationSongsRepository.cpp PUBLIC include/application-bell-relaxation/ApplicationBellRelaxation.hpp diff --git a/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.cpp b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c39f5732ab75fa0c8e4eed2a27236a447f71902 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "RelaxationSongsModel.hpp" +#include "common/options/OptionBellMenu.hpp" + +namespace app::relaxation +{ + + RelaxationSongsProvider::RelaxationSongsProvider(ApplicationCommon *app) : DatabaseModel(app) + {} + + RelaxationSongsModel::RelaxationSongsModel( + ApplicationCommon *application, std::unique_ptr soundsRepository) + : RelaxationSongsProvider(application), application(application), songsRepository{std::move(soundsRepository)} + {} + + void RelaxationSongsModel::createData(OnActivateCallback callback) + { + activateCallback = callback; + + songsRepository->init(); + } + + unsigned int RelaxationSongsModel::requestRecordsCount() + { + return songsRepository->getRecordsCount(); + } + unsigned int RelaxationSongsModel::getMinimalItemSpaceRequired() const + { + return style::bell_options::h + 2 * style::bell_options::option_margin; + } + gui::ListItem *RelaxationSongsModel::getItem(gui::Order order) + { + const auto sound = getRecord(order); + if (!sound) { + return nullptr; + } + + auto item = new gui::option::OptionBellMenu( + sound->tags.title, + [=](gui::Item &item) { + activateCallback(*sound); + return true; + }, + [=](gui::Item &item) { return true; }, + nullptr); + + return item->build(); + } + void RelaxationSongsModel::requestRecords(std::uint32_t offset, std::uint32_t limit) + { + songsRepository->getMusicFiles( + offset, + limit, + [this](const std::vector &records, + unsigned int repoRecordsCount) { return onMusicListRetrieved(records, repoRecordsCount); }); + } + bool RelaxationSongsModel::onMusicListRetrieved( + const std::vector &records, unsigned int repoRecordsCount) + { + if (list != nullptr && recordsCount != repoRecordsCount) { + recordsCount = repoRecordsCount; + list->reSendLastRebuildRequest(); + return false; + } + return updateRecords(records); + } + bool RelaxationSongsModel::updateRecords(std::vector records) + { + DatabaseModel::updateRecords(std::move(records)); + list->onProviderDataUpdate(); + return true; + } +} // namespace app::relaxation diff --git a/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.hpp b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0bf847fd06206198fa8419c1f24980132c83d7f3 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsModel.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "RelaxationSongsRepository.hpp" +#include +#include + +namespace app::relaxation +{ + + class RelaxationSongsProvider : public app::DatabaseModel, + public gui::ListItemProvider + { + public: + using OnActivateCallback = + std::function; + explicit RelaxationSongsProvider(ApplicationCommon *application); + virtual void createData(OnActivateCallback activateCallback) = 0; + }; + + class RelaxationSongsModel : public RelaxationSongsProvider + { + private: + ApplicationCommon *application; + std::unique_ptr songsRepository; + OnActivateCallback activateCallback{nullptr}; + + bool onMusicListRetrieved(const std::vector &records, + unsigned int repoRecordsCount); + [[nodiscard]] bool updateRecords(std::vector records) override; + + public: + explicit RelaxationSongsModel(ApplicationCommon *application, + std::unique_ptr soundsRepository); + + unsigned int requestRecordsCount() override; + + [[nodiscard]] unsigned int getMinimalItemSpaceRequired() const override; + + gui::ListItem *getItem(gui::Order order) override; + + void requestRecords(std::uint32_t offset, std::uint32_t limit) override; + + void createData(OnActivateCallback activateCallback) override; + }; +} // namespace app::relaxation diff --git a/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.cpp b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3045225f31ed34f7e1520e6ee1f39fc835bc2600 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md +#include "RelaxationSongsRepository.hpp" +#include +#include +#include +#include + +namespace +{ + std::uint32_t calculateOffset(std::uint32_t offset, std::uint32_t filesCount) + { + if (offset >= filesCount) { + return offset - filesCount; + } + return offset; + } + std::pair calculateNewOffsetAndLimit(std::uint32_t offset, + std::uint32_t limit, + std::uint32_t loadedFiles) + { + const auto newLimit = limit - loadedFiles; + const auto newOffset = offset + loadedFiles; + return {newOffset, newLimit}; + } +} // namespace +namespace app::relaxation +{ + + RelaxationSongsRepository::RelaxationSongsRepository(ApplicationCommon *application, + const std::map &pathPrefixes) + : app::AsyncCallbackReceiver{application}, application{application}, pathPrefixes{pathPrefixes} + {} + + void RelaxationSongsRepository::init() + { + for (const auto &[musicType, musicPath] : pathPrefixes) { + updateFilesCount(musicType, musicPath); + } + } + + void RelaxationSongsRepository::updateFilesCount(const MusicType &type, const std::string &path) + { + auto query = std::make_unique(path); + auto task = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::MultimediaFiles); + task->setCallback([this, &type](auto response) { + auto result = dynamic_cast(response); + if (result == nullptr) { + return false; + } + return updateCountCallback(type, result->getCount()); + }); + task->execute(application, this); + } + + bool RelaxationSongsRepository::updateCountCallback(const MusicType &type, std::uint32_t count) + { + filesPerType[type] = count; + return true; + } + + void RelaxationSongsRepository::getMusicFiles( + const MusicType &musicType, + std::uint32_t offset, + std::uint32_t limit, + const RelaxationSongsRepository::OnGetMusicFilesListCallback &viewUpdateCallback) + { + auto taskCallback = [this, viewUpdateCallback, offset, musicType](auto response) { + auto result = dynamic_cast(response); + if (result == nullptr) { + return false; + } + for (auto &record : result->getResult()) { + musicFilesViewCache.records.push_back(record); + } + musicFilesViewCache.recordsOffset = offset; + musicFilesViewCache.recordsCount = getRecordsCount(); + + if (viewUpdateCallback) { + viewUpdateCallback(musicFilesViewCache.records, musicFilesViewCache.recordsCount); + } + updateCountCallback(musicType, result->getCount()); + return true; + }; + + auto query = std::make_unique( + std::vector{pathPrefixes[musicType]}, offset, limit); + auto task = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::MultimediaFiles); + task->setCallback(taskCallback); + task->execute(application, this); + } + + std::uint32_t RelaxationSongsRepository::getRecordsCount() + { + return std::accumulate(filesPerType.begin(), + filesPerType.end(), + 0, + [](const std::uint32_t sum, const auto &record) { return sum + record.second; }); + } + + void RelaxationSongsRepository::getMusicFiles( + std::uint32_t offset, + std::uint32_t limit, + const RelaxationSongsRepository::OnGetMusicFilesListCallback &callback) + { + const auto skipViewUpdate = []([[maybe_unused]] const auto &sound, [[maybe_unused]] auto count) { + return true; + }; + musicFilesViewCache.records.clear(); + std::uint32_t totalFilesCount{0}; + const auto lastFileIndex = offset + limit; + + if (filesPerType.empty()) { + getMusicFiles(MusicType::Relaxation, offset, limit, callback); + } + + for (const auto &[type, filesCount] : filesPerType) { + totalFilesCount += filesCount; + if (const auto newOffset = calculateOffset(offset, filesCount); newOffset != offset) { + offset = newOffset; + } + else if (lastFileIndex <= totalFilesCount) { + getMusicFiles(type, offset, limit, callback); + break; + } + else { + const auto filesToLoad = filesCount - offset; + getMusicFiles(type, offset, filesToLoad, skipViewUpdate); + std::tie(offset, limit) = calculateNewOffsetAndLimit(offset, limit, filesToLoad); + offset = calculateOffset(offset, filesCount); + } + } + } + +} // namespace app::relaxation diff --git a/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.hpp b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..13edde03d7bf5248e26f5785bd358e1c5038c0ae --- /dev/null +++ b/products/BellHybrid/apps/application-bell-relaxation/model/RelaxationSongsRepository.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include +namespace app::relaxation +{ + enum class MusicType + { + Relaxation, + User + }; + + class RelaxationSongsRepository : public app::AsyncCallbackReceiver + { + public: + using OnGetMusicFilesListCallback = + std::function &, std::uint32_t)>; + + explicit RelaxationSongsRepository(ApplicationCommon *application, + const std::map &pathPrefixes); + void init(); + void getMusicFiles(std::uint32_t offset, + std::uint32_t limit, + const OnGetMusicFilesListCallback &viewUpdateCallback); + + std::uint32_t getRecordsCount(); + + private: + ApplicationCommon *application; + std::map pathPrefixes; + std::map filesPerType; + music::FilesCache musicFilesViewCache; + void updateFilesCount(const MusicType &type, const std::string &path); + bool updateCountCallback(const MusicType &type, std::uint32_t count); + void getMusicFiles(const MusicType &musicType, + std::uint32_t offset, + std::uint32_t limit, + const OnGetMusicFilesListCallback &viewUpdateCallback); + }; +} // namespace app::relaxation diff --git a/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.cpp b/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.cpp index 1a794ec7497fadce94945723586783578c11b29f..951e6db04458f64698150e2fcc86e1da96bb2c92 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.cpp +++ b/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.cpp @@ -4,31 +4,27 @@ #include "RelaxationMainWindowPresenter.hpp" #include -namespace -{ - constexpr auto offset = 0; - constexpr auto filesLimitPerPath = 100; -} // namespace - namespace app::relaxation { - RelaxationMainWindowPresenter::RelaxationMainWindowPresenter( - std::unique_ptr soundsRepository) - : soundsRepository{std::move(soundsRepository)} + RelaxationMainWindowPresenter::RelaxationMainWindowPresenter(std::unique_ptr songsModel) + : songsModel{std::move(songsModel)} {} - void RelaxationMainWindowPresenter::loadAudioRecords() + void RelaxationMainWindowPresenter::createData(RelaxationSongsModel::OnActivateCallback activateCallback) + { + songsModel->createData(activateCallback); + updateViewState(); + } + void RelaxationMainWindowPresenter::updateViewState() + { + auto view = getView(); + if (view != nullptr) { + view->updateViewState(); + } + } + + std::shared_ptr RelaxationMainWindowPresenter::getSongsModel() { - soundsRepository->getMusicFilesListByPaths( - offset, - filesLimitPerPath, - [this](const std::vector &records, - unsigned int repoRecordsCount) { - getView()->setSoundsList(records); - if (repoRecordsCount > filesLimitPerPath) { - getView()->handleError(); - } - return true; - }); + return songsModel; } } // namespace app::relaxation diff --git a/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.hpp b/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.hpp index dca53e7a45693573ccb441f96a96fbdb94da9966..94d72e648b96746b7f10f43d541421b358d2c09b 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.hpp +++ b/products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationMainWindowPresenter.hpp @@ -3,6 +3,7 @@ #pragma once +#include "model/RelaxationSongsModel.hpp" #include #include #include @@ -13,6 +14,7 @@ namespace app::music } namespace app::relaxation { + class RelaxationMainWindowContract { public: @@ -21,24 +23,30 @@ namespace app::relaxation public: virtual ~View() = default; - virtual void setSoundsList(std::vector songs) = 0; + virtual void updateViewState() = 0; virtual void handleError() = 0; }; class Presenter : public BasePresenter { + public: - virtual void loadAudioRecords() = 0; + virtual void createData(RelaxationSongsModel::OnActivateCallback activateCallback) = 0; + virtual void updateViewState() = 0; + virtual std::shared_ptr getSongsModel() = 0; }; }; class RelaxationMainWindowPresenter : public RelaxationMainWindowContract::Presenter { - std::unique_ptr soundsRepository; - void loadAudioRecords() override; + private: + std::shared_ptr songsModel; + void createData(RelaxationSongsModel::OnActivateCallback activateCallback) override; + void updateViewState() override; + std::shared_ptr getSongsModel() override; public: - explicit RelaxationMainWindowPresenter(std::unique_ptr soundsRepository); + explicit RelaxationMainWindowPresenter(std::unique_ptr songsModel); }; } // namespace app::relaxation diff --git a/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp b/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp index 3dbf87ed2485c42399a46d84162c3aae34275445..08f3695e6f560f40ff81eed239aa54bda6688529 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp +++ b/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp @@ -5,54 +5,53 @@ #include #include #include +#include "common/options/BellOptionsNavigation.hpp" #include #include -namespace -{ - constexpr auto maxDisplayedTitleLength = 30U; - constexpr auto incompleteSequenceCharCode = '\342'; -} // namespace namespace gui { RelaxationMainWindow::RelaxationMainWindow( app::ApplicationCommon *app, std::unique_ptr &&presenter) - : BellOptionWindow(app, gui::name::window::main_window), presenter{std::move(presenter)} + : AppWindow(app, gui::name::window::main_window), presenter{std::move(presenter)} { this->presenter->attach(this); buildInterface(); - setListTitle(utils::translate("app_bellmain_relaxation")); } - void RelaxationMainWindow::setSoundsList(std::vector sounds) + void RelaxationMainWindow::buildInterface() { - std::list menuOptionList; - auto addRecord = [&](const db::multimedia_files::MultimediaFilesRecord &sound) { - menuOptionList.emplace_back(std::make_unique( - sound.tags.title, - [=](gui::Item &item) { - onActivated(sound); - return true; - }, - [=](gui::Item &item) { return true; }, - this)); + AppWindow::buildInterface(); + + statusBar->setVisible(false); + header->setTitleVisibility(false); + navBar->setVisible(false); + + songList = new gui::ListViewWithArrows( + this, 0, 0, style::window_width, style::window_height, presenter->getSongsModel()); + songList->applySizeRestrictions(style::bell_options_list::w, + style::bell_options_list::h, + style::bell_options_list::outer_layouts_h, + style::bell_options_list::outer_layouts_margin); + + songList->setListTitle(utils::translate("app_bellmain_relaxation")); + + auto storedCallback = songList->inputCallback; + songList->inputCallback = [&, storedCallback](Item &item, const InputEvent &event) { + return storedCallback(item, invertNavigationDirection(event)); }; - for (const auto &sound : sounds) { - addRecord(sound); - } - addOptions(std::move(menuOptionList)); - } + setFocusItem(songList); - void RelaxationMainWindow::buildInterface() - { - BellOptionWindow::buildInterface(); - presenter->loadAudioRecords(); + presenter->createData([this](const db::multimedia_files::MultimediaFilesRecord &selectedSound) { + activate(selectedSound); + return true; + }); } - void RelaxationMainWindow::onActivated(const db::multimedia_files::MultimediaFilesRecord &selectedSound) + void RelaxationMainWindow::activate(const db::multimedia_files::MultimediaFilesRecord &selectedSound) { auto audioContext = std::make_unique(selectedSound); auto switchData = std::make_unique(std::move(audioContext)); @@ -65,9 +64,9 @@ namespace gui application->switchWindow(gui::window::name::relaxationError, std::move(switchData)); } - void RelaxationMainWindow::rebuild() + void RelaxationMainWindow::updateViewState() { - presenter->loadAudioRecords(); + songList->rebuildList(gui::listview::RebuildType::InPlace); } } // namespace gui diff --git a/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.hpp b/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.hpp index 43d215b5dbb17c659b2b43522d6deed287a12e7c..ff7c25967308dfa656266450259083d0d256ca9f 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.hpp +++ b/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.hpp @@ -9,7 +9,7 @@ namespace gui { - class RelaxationMainWindow : public BellOptionWindow, public app::relaxation::RelaxationMainWindowContract::View + class RelaxationMainWindow : public AppWindow, public app::relaxation::RelaxationMainWindowContract::View { public: RelaxationMainWindow(app::ApplicationCommon *app, @@ -18,10 +18,11 @@ namespace gui private: std::unique_ptr presenter; + gui::ListViewWithArrows *songList = nullptr; + void buildInterface() override; void handleError() override; - void rebuild() override; - void setSoundsList(std::vector soundsTags); - void onActivated(const db::multimedia_files::MultimediaFilesRecord &selectedSound); + void updateViewState() override; + void activate(const db::multimedia_files::MultimediaFilesRecord &selectedSound); }; } // namespace gui diff --git a/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningProgressWindow.cpp b/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningProgressWindow.cpp index 891fef8b4693fe2822be95ccb273cad531891e8b..67f726e5f0f47b52e959b3e5db64e93fb7d41538 100644 --- a/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningProgressWindow.cpp +++ b/products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningProgressWindow.cpp @@ -7,7 +7,6 @@ #include #include -#include