Use databinding for the top bar. It's so nice now!
This commit is contained in:
@@ -336,7 +336,6 @@ void RegisterDbDump() {
|
|||||||
esp_console_cmd_register(&cmd);
|
esp_console_cmd_register(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_APPTRACE_ENABLE
|
|
||||||
int CmdTasks(int argc, char** argv) {
|
int CmdTasks(int argc, char** argv) {
|
||||||
if (!configUSE_TRACE_FACILITY) {
|
if (!configUSE_TRACE_FACILITY) {
|
||||||
std::cout << "configUSE_TRACE_FACILITY must be enabled" << std::endl;
|
std::cout << "configUSE_TRACE_FACILITY must be enabled" << std::endl;
|
||||||
@@ -446,7 +445,6 @@ void RegisterTasks() {
|
|||||||
.argtable = NULL};
|
.argtable = NULL};
|
||||||
esp_console_cmd_register(&cmd);
|
esp_console_cmd_register(&cmd);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int CmdHeaps(int argc, char** argv) {
|
int CmdHeaps(int argc, char** argv) {
|
||||||
static const std::pmr::string usage = "usage: heaps";
|
static const std::pmr::string usage = "usage: heaps";
|
||||||
@@ -638,9 +636,7 @@ auto AppConsole::RegisterExtraComponents() -> void {
|
|||||||
RegisterDbTracks();
|
RegisterDbTracks();
|
||||||
RegisterDbIndex();
|
RegisterDbIndex();
|
||||||
RegisterDbDump();
|
RegisterDbDump();
|
||||||
#if CONFIG_APPTRACE_ENABLE
|
|
||||||
RegisterTasks();
|
RegisterTasks();
|
||||||
#endif
|
|
||||||
|
|
||||||
RegisterHeaps();
|
RegisterHeaps();
|
||||||
|
|
||||||
|
|||||||
+13
-5
@@ -77,15 +77,16 @@ auto Battery::Update() -> void {
|
|||||||
*charge_state == ChargeStatus::kChargingFast ||
|
*charge_state == ChargeStatus::kChargingFast ||
|
||||||
*charge_state == ChargeStatus::kFullCharge;
|
*charge_state == ChargeStatus::kFullCharge;
|
||||||
|
|
||||||
if (!state_ || state_->is_charging != is_charging ||
|
if (state_ && state_->is_charging == is_charging &&
|
||||||
state_->percent != percent) {
|
state_->percent == percent) {
|
||||||
EmitEvent();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ = BatteryState{
|
state_ = BatteryState{
|
||||||
.percent = percent,
|
.percent = percent,
|
||||||
.is_charging = is_charging,
|
.is_charging = is_charging,
|
||||||
};
|
};
|
||||||
|
EmitEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Battery::State() -> std::optional<BatteryState> {
|
auto Battery::State() -> std::optional<BatteryState> {
|
||||||
@@ -94,8 +95,15 @@ auto Battery::State() -> std::optional<BatteryState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Battery::EmitEvent() -> void {
|
auto Battery::EmitEvent() -> void {
|
||||||
events::System().Dispatch(system_fsm::BatteryStateChanged{});
|
auto state = state_;
|
||||||
events::Ui().Dispatch(system_fsm::BatteryStateChanged{});
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
system_fsm::BatteryStateChanged ev{
|
||||||
|
.new_state = *state,
|
||||||
|
};
|
||||||
|
events::System().Dispatch(ev);
|
||||||
|
events::Ui().Dispatch(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace battery
|
} // namespace battery
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "battery.hpp"
|
||||||
#include "database.hpp"
|
#include "database.hpp"
|
||||||
#include "service_locator.hpp"
|
#include "service_locator.hpp"
|
||||||
#include "tinyfsm.hpp"
|
#include "tinyfsm.hpp"
|
||||||
@@ -54,7 +55,9 @@ struct HasPhonesChanged : tinyfsm::Event {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ChargingStatusChanged : tinyfsm::Event {};
|
struct ChargingStatusChanged : tinyfsm::Event {};
|
||||||
struct BatteryStateChanged : tinyfsm::Event {};
|
struct BatteryStateChanged : tinyfsm::Event {
|
||||||
|
battery::Battery::BatteryState new_state;
|
||||||
|
};
|
||||||
|
|
||||||
struct BluetoothDevicesChanged : tinyfsm::Event {};
|
struct BluetoothDevicesChanged : tinyfsm::Event {};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "battery.hpp"
|
||||||
|
#include "bindey/property.h"
|
||||||
|
|
||||||
|
#include "track.hpp"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
namespace models {
|
||||||
|
|
||||||
|
struct TopBar {
|
||||||
|
bindey::property<battery::Battery::BatteryState> battery_state;
|
||||||
|
|
||||||
|
// Shared with the Playback model
|
||||||
|
bindey::property<bool>& is_playing;
|
||||||
|
bindey::property<std::optional<database::TrackId>>& current_track;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace models
|
||||||
|
} // namespace ui
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "core/lv_obj_tree.h"
|
#include "core/lv_obj_tree.h"
|
||||||
#include "event_binding.hpp"
|
#include "event_binding.hpp"
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "nod/nod.hpp"
|
#include "nod/nod.hpp"
|
||||||
#include "widget_top_bar.hpp"
|
#include "widget_top_bar.hpp"
|
||||||
|
|
||||||
@@ -37,8 +38,6 @@ class Screen {
|
|||||||
*/
|
*/
|
||||||
virtual auto Tick() -> void {}
|
virtual auto Tick() -> void {}
|
||||||
|
|
||||||
auto UpdateTopBar(const widgets::TopBar::State& state) -> void;
|
|
||||||
|
|
||||||
auto root() -> lv_obj_t* { return root_; }
|
auto root() -> lv_obj_t* { return root_; }
|
||||||
auto content() -> lv_obj_t* { return content_; }
|
auto content() -> lv_obj_t* { return content_; }
|
||||||
|
|
||||||
@@ -52,8 +51,9 @@ class Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
auto CreateTopBar(lv_obj_t* parent, const widgets::TopBar::Configuration&)
|
auto CreateTopBar(lv_obj_t* parent,
|
||||||
-> widgets::TopBar*;
|
const widgets::TopBar::Configuration&,
|
||||||
|
models::TopBar& model) -> widgets::TopBar*;
|
||||||
|
|
||||||
std::pmr::vector<bindey::scoped_binding> data_bindings_;
|
std::pmr::vector<bindey::scoped_binding> data_bindings_;
|
||||||
std::pmr::vector<std::unique_ptr<EventBinding>> event_bindings_;
|
std::pmr::vector<std::unique_ptr<EventBinding>> event_bindings_;
|
||||||
@@ -78,7 +78,9 @@ class Screen {
|
|||||||
|
|
||||||
class MenuScreen : public Screen {
|
class MenuScreen : public Screen {
|
||||||
public:
|
public:
|
||||||
MenuScreen(const std::pmr::string& title, bool show_back_button = true);
|
MenuScreen(models::TopBar&,
|
||||||
|
const std::pmr::string& title,
|
||||||
|
bool show_back_button = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "index.hpp"
|
#include "index.hpp"
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "screen.hpp"
|
#include "screen.hpp"
|
||||||
#include "screen_settings.hpp"
|
#include "screen_settings.hpp"
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ namespace screens {
|
|||||||
|
|
||||||
class Menu : public MenuScreen {
|
class Menu : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
explicit Menu(std::vector<database::IndexInfo> indexes);
|
explicit Menu(models::TopBar&, std::vector<database::IndexInfo> indexes);
|
||||||
~Menu();
|
~Menu();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "database.hpp"
|
#include "database.hpp"
|
||||||
#include "future_fetcher.hpp"
|
#include "future_fetcher.hpp"
|
||||||
#include "model_playback.hpp"
|
#include "model_playback.hpp"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "screen.hpp"
|
#include "screen.hpp"
|
||||||
#include "track.hpp"
|
#include "track.hpp"
|
||||||
#include "track_queue.hpp"
|
#include "track_queue.hpp"
|
||||||
@@ -31,7 +32,8 @@ namespace screens {
|
|||||||
*/
|
*/
|
||||||
class Playing : public Screen {
|
class Playing : public Screen {
|
||||||
public:
|
public:
|
||||||
explicit Playing(models::Playback& playback_model,
|
explicit Playing(models::TopBar&,
|
||||||
|
models::Playback& playback_model,
|
||||||
std::weak_ptr<database::Database> db,
|
std::weak_ptr<database::Database> db,
|
||||||
audio::TrackQueue& queue);
|
audio::TrackQueue& queue);
|
||||||
~Playing();
|
~Playing();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "index.hpp"
|
#include "index.hpp"
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "nvs.hpp"
|
#include "nvs.hpp"
|
||||||
#include "screen.hpp"
|
#include "screen.hpp"
|
||||||
|
|
||||||
@@ -26,12 +27,12 @@ namespace screens {
|
|||||||
|
|
||||||
class Settings : public MenuScreen {
|
class Settings : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
Settings();
|
Settings(models::TopBar&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Bluetooth : public MenuScreen {
|
class Bluetooth : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
Bluetooth(drivers::Bluetooth& bt, drivers::NvsStorage& nvs);
|
Bluetooth(models::TopBar&, drivers::Bluetooth& bt, drivers::NvsStorage& nvs);
|
||||||
|
|
||||||
auto ChangeEnabledState(bool enabled) -> void;
|
auto ChangeEnabledState(bool enabled) -> void;
|
||||||
auto RefreshDevicesList() -> void;
|
auto RefreshDevicesList() -> void;
|
||||||
@@ -53,7 +54,7 @@ class Bluetooth : public MenuScreen {
|
|||||||
|
|
||||||
class Headphones : public MenuScreen {
|
class Headphones : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
Headphones(drivers::NvsStorage& nvs);
|
Headphones(models::TopBar&, drivers::NvsStorage& nvs);
|
||||||
|
|
||||||
auto ChangeMaxVolume(uint8_t index) -> void;
|
auto ChangeMaxVolume(uint8_t index) -> void;
|
||||||
auto ChangeCustomVolume(int8_t diff) -> void;
|
auto ChangeCustomVolume(int8_t diff) -> void;
|
||||||
@@ -71,7 +72,9 @@ class Headphones : public MenuScreen {
|
|||||||
|
|
||||||
class Appearance : public MenuScreen {
|
class Appearance : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
Appearance(drivers::NvsStorage& nvs, drivers::Display& display);
|
Appearance(models::TopBar&,
|
||||||
|
drivers::NvsStorage& nvs,
|
||||||
|
drivers::Display& display);
|
||||||
|
|
||||||
auto ChangeBrightness(uint_fast8_t) -> void;
|
auto ChangeBrightness(uint_fast8_t) -> void;
|
||||||
auto CommitBrightness() -> void;
|
auto CommitBrightness() -> void;
|
||||||
@@ -86,22 +89,22 @@ class Appearance : public MenuScreen {
|
|||||||
|
|
||||||
class InputMethod : public MenuScreen {
|
class InputMethod : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
InputMethod();
|
InputMethod(models::TopBar&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Storage : public MenuScreen {
|
class Storage : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
Storage();
|
Storage(models::TopBar&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FirmwareUpdate : public MenuScreen {
|
class FirmwareUpdate : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
FirmwareUpdate();
|
FirmwareUpdate(models::TopBar&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class About : public MenuScreen {
|
class About : public MenuScreen {
|
||||||
public:
|
public:
|
||||||
About();
|
About(models::TopBar&);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace screens
|
} // namespace screens
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
#include "database.hpp"
|
#include "database.hpp"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "screen.hpp"
|
#include "screen.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@@ -22,6 +23,7 @@ namespace screens {
|
|||||||
class TrackBrowser : public Screen {
|
class TrackBrowser : public Screen {
|
||||||
public:
|
public:
|
||||||
TrackBrowser(
|
TrackBrowser(
|
||||||
|
models::TopBar&,
|
||||||
std::weak_ptr<database::Database> db,
|
std::weak_ptr<database::Database> db,
|
||||||
const std::pmr::string& title,
|
const std::pmr::string& title,
|
||||||
std::future<database::Result<database::IndexRecord>*>&& initial_page);
|
std::future<database::Result<database::IndexRecord>*>&& initial_page);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "gpios.hpp"
|
#include "gpios.hpp"
|
||||||
#include "lvgl_task.hpp"
|
#include "lvgl_task.hpp"
|
||||||
#include "model_playback.hpp"
|
#include "model_playback.hpp"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "nvs.hpp"
|
#include "nvs.hpp"
|
||||||
#include "relative_wheel.hpp"
|
#include "relative_wheel.hpp"
|
||||||
#include "screen_playing.hpp"
|
#include "screen_playing.hpp"
|
||||||
@@ -82,7 +83,6 @@ class UiState : public tinyfsm::Fsm<UiState> {
|
|||||||
protected:
|
protected:
|
||||||
void PushScreen(std::shared_ptr<Screen>);
|
void PushScreen(std::shared_ptr<Screen>);
|
||||||
void PopScreen();
|
void PopScreen();
|
||||||
void UpdateTopBar();
|
|
||||||
|
|
||||||
static std::unique_ptr<UiTask> sTask;
|
static std::unique_ptr<UiTask> sTask;
|
||||||
static std::shared_ptr<system_fsm::ServiceLocator> sServices;
|
static std::shared_ptr<system_fsm::ServiceLocator> sServices;
|
||||||
@@ -94,8 +94,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
|
|||||||
static std::shared_ptr<Modal> sCurrentModal;
|
static std::shared_ptr<Modal> sCurrentModal;
|
||||||
|
|
||||||
static models::Playback sPlaybackModel;
|
static models::Playback sPlaybackModel;
|
||||||
|
static models::TopBar sTopBarModel;
|
||||||
static bindey::property<battery::Battery::BatteryState> sPropBatteryState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace states {
|
namespace states {
|
||||||
|
|||||||
@@ -9,9 +9,11 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "bindey/binding.h"
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
#include "memory_resource.hpp"
|
#include "memory_resource.hpp"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
@@ -24,33 +26,18 @@ class TopBar {
|
|||||||
std::pmr::string title;
|
std::pmr::string title;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PlaybackState {
|
explicit TopBar(lv_obj_t* parent,
|
||||||
kIdle,
|
const Configuration& config,
|
||||||
kPaused,
|
models::TopBar& model);
|
||||||
kPlaying,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct State {
|
|
||||||
PlaybackState playback_state;
|
|
||||||
uint_fast8_t battery_percent;
|
|
||||||
bool is_charging;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit TopBar(lv_obj_t* parent, const Configuration& config);
|
|
||||||
|
|
||||||
auto root() -> lv_obj_t* { return container_; }
|
auto root() -> lv_obj_t* { return container_; }
|
||||||
auto button() -> lv_obj_t* { return back_button_; }
|
auto button() -> lv_obj_t* { return back_button_; }
|
||||||
|
|
||||||
auto Update(const State&) -> void;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lv_obj_t* container_;
|
std::vector<bindey::scoped_binding> bindings_;
|
||||||
|
|
||||||
|
lv_obj_t* container_;
|
||||||
lv_obj_t* back_button_;
|
lv_obj_t* back_button_;
|
||||||
lv_obj_t* title_;
|
|
||||||
lv_obj_t* playback_;
|
|
||||||
lv_obj_t* battery_;
|
|
||||||
lv_obj_t* charging_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
|
|||||||
+8
-11
@@ -12,6 +12,7 @@
|
|||||||
#include "core/lv_obj_tree.h"
|
#include "core/lv_obj_tree.h"
|
||||||
#include "misc/lv_area.h"
|
#include "misc/lv_area.h"
|
||||||
#include "misc/lv_color.h"
|
#include "misc/lv_color.h"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "widget_top_bar.hpp"
|
#include "widget_top_bar.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@@ -40,24 +41,20 @@ Screen::~Screen() {
|
|||||||
lv_obj_del(root_);
|
lv_obj_del(root_);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Screen::UpdateTopBar(const widgets::TopBar::State& state) -> void {
|
|
||||||
if (top_bar_) {
|
|
||||||
top_bar_->Update(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Screen::CreateTopBar(lv_obj_t* parent,
|
auto Screen::CreateTopBar(lv_obj_t* parent,
|
||||||
const widgets::TopBar::Configuration& config)
|
const widgets::TopBar::Configuration& config,
|
||||||
-> widgets::TopBar* {
|
models::TopBar& model) -> widgets::TopBar* {
|
||||||
assert(top_bar_ == nullptr);
|
assert(top_bar_ == nullptr);
|
||||||
top_bar_ = std::make_unique<widgets::TopBar>(parent, config);
|
top_bar_ = std::make_unique<widgets::TopBar>(parent, config, model);
|
||||||
if (top_bar_->button()) {
|
if (top_bar_->button()) {
|
||||||
lv_group_add_obj(group_, top_bar_->button());
|
lv_group_add_obj(group_, top_bar_->button());
|
||||||
}
|
}
|
||||||
return top_bar_.get();
|
return top_bar_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuScreen::MenuScreen(const std::pmr::string& title, bool show_back_button)
|
MenuScreen::MenuScreen(models::TopBar& top_bar_model,
|
||||||
|
const std::pmr::string& title,
|
||||||
|
bool show_back_button)
|
||||||
: Screen() {
|
: Screen() {
|
||||||
lv_group_set_wrap(group_, false);
|
lv_group_set_wrap(group_, false);
|
||||||
|
|
||||||
@@ -70,7 +67,7 @@ MenuScreen::MenuScreen(const std::pmr::string& title, bool show_back_button)
|
|||||||
.show_back_button = show_back_button,
|
.show_back_button = show_back_button,
|
||||||
.title = title.c_str(),
|
.title = title.c_str(),
|
||||||
};
|
};
|
||||||
CreateTopBar(content_, config);
|
CreateTopBar(content_, config, top_bar_model);
|
||||||
|
|
||||||
content_ = lv_obj_create(content_);
|
content_ = lv_obj_create(content_);
|
||||||
lv_obj_set_flex_grow(content_, 1);
|
lv_obj_set_flex_grow(content_, 1);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "hal/lv_hal_disp.h"
|
#include "hal/lv_hal_disp.h"
|
||||||
#include "index.hpp"
|
#include "index.hpp"
|
||||||
#include "misc/lv_area.h"
|
#include "misc/lv_area.h"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "ui_events.hpp"
|
#include "ui_events.hpp"
|
||||||
#include "ui_fsm.hpp"
|
#include "ui_fsm.hpp"
|
||||||
#include "widget_top_bar.hpp"
|
#include "widget_top_bar.hpp"
|
||||||
@@ -45,8 +46,8 @@ static void index_click_cb(lv_event_t* ev) {
|
|||||||
events::Ui().Dispatch(internal::IndexSelected{.index = *index});
|
events::Ui().Dispatch(internal::IndexSelected{.index = *index});
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu::Menu(std::vector<database::IndexInfo> indexes)
|
Menu::Menu(models::TopBar& top_bar, std::vector<database::IndexInfo> indexes)
|
||||||
: MenuScreen(" ", false), indexes_(indexes) {
|
: MenuScreen(top_bar, " ", false), indexes_(indexes) {
|
||||||
lv_obj_t* list = lv_list_create(content_);
|
lv_obj_t* list = lv_list_create(content_);
|
||||||
lv_obj_set_size(list, lv_pct(100), lv_pct(100));
|
lv_obj_set_size(list, lv_pct(100), lv_pct(100));
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "misc/lv_color.h"
|
#include "misc/lv_color.h"
|
||||||
#include "misc/lv_txt.h"
|
#include "misc/lv_txt.h"
|
||||||
#include "model_playback.hpp"
|
#include "model_playback.hpp"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "track.hpp"
|
#include "track.hpp"
|
||||||
#include "ui_events.hpp"
|
#include "ui_events.hpp"
|
||||||
#include "ui_fsm.hpp"
|
#include "ui_fsm.hpp"
|
||||||
@@ -101,7 +102,8 @@ auto Playing::next_up_label(lv_obj_t* parent, const std::pmr::string& text)
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
Playing::Playing(models::Playback& playback_model,
|
Playing::Playing(models::TopBar& top_bar_model,
|
||||||
|
models::Playback& playback_model,
|
||||||
std::weak_ptr<database::Database> db,
|
std::weak_ptr<database::Database> db,
|
||||||
audio::TrackQueue& queue)
|
audio::TrackQueue& queue)
|
||||||
: db_(db),
|
: db_(db),
|
||||||
@@ -158,7 +160,7 @@ Playing::Playing(models::Playback& playback_model,
|
|||||||
.show_back_button = true,
|
.show_back_button = true,
|
||||||
.title = "Now Playing",
|
.title = "Now Playing",
|
||||||
};
|
};
|
||||||
CreateTopBar(above_fold_container, config);
|
CreateTopBar(above_fold_container, config, top_bar_model);
|
||||||
|
|
||||||
lv_obj_t* info_container = lv_obj_create(above_fold_container);
|
lv_obj_t* info_container = lv_obj_create(above_fold_container);
|
||||||
lv_obj_set_layout(info_container, LV_LAYOUT_FLEX);
|
lv_obj_set_layout(info_container, LV_LAYOUT_FLEX);
|
||||||
|
|||||||
+18
-11
@@ -29,6 +29,7 @@
|
|||||||
#include "index.hpp"
|
#include "index.hpp"
|
||||||
#include "misc/lv_anim.h"
|
#include "misc/lv_anim.h"
|
||||||
#include "misc/lv_area.h"
|
#include "misc/lv_area.h"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "nvs.hpp"
|
#include "nvs.hpp"
|
||||||
#include "screen.hpp"
|
#include "screen.hpp"
|
||||||
#include "ui_events.hpp"
|
#include "ui_events.hpp"
|
||||||
@@ -64,7 +65,7 @@ static void sub_menu(lv_obj_t* list,
|
|||||||
reinterpret_cast<void*>(static_cast<uintptr_t>(page)));
|
reinterpret_cast<void*>(static_cast<uintptr_t>(page)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::Settings() : MenuScreen("Settings") {
|
Settings::Settings(models::TopBar& bar) : MenuScreen(bar, "Settings") {
|
||||||
lv_obj_t* list = lv_list_create(content_);
|
lv_obj_t* list = lv_list_create(content_);
|
||||||
lv_obj_set_size(list, lv_pct(100), lv_pct(100));
|
lv_obj_set_size(list, lv_pct(100), lv_pct(100));
|
||||||
|
|
||||||
@@ -113,8 +114,10 @@ static auto select_device_cb(lv_event_t* ev) {
|
|||||||
instance->OnDeviceSelected(lv_obj_get_index(ev->target));
|
instance->OnDeviceSelected(lv_obj_get_index(ev->target));
|
||||||
}
|
}
|
||||||
|
|
||||||
Bluetooth::Bluetooth(drivers::Bluetooth& bt, drivers::NvsStorage& nvs)
|
Bluetooth::Bluetooth(models::TopBar& bar,
|
||||||
: MenuScreen("Bluetooth"), bt_(bt), nvs_(nvs) {
|
drivers::Bluetooth& bt,
|
||||||
|
drivers::NvsStorage& nvs)
|
||||||
|
: MenuScreen(bar, "Bluetooth"), bt_(bt), nvs_(nvs) {
|
||||||
lv_obj_t* toggle_container = settings_container(content_);
|
lv_obj_t* toggle_container = settings_container(content_);
|
||||||
lv_obj_t* toggle_label = lv_label_create(toggle_container);
|
lv_obj_t* toggle_label = lv_label_create(toggle_container);
|
||||||
lv_label_set_text(toggle_label, "Enable");
|
lv_label_set_text(toggle_label, "Enable");
|
||||||
@@ -268,8 +271,8 @@ static void decrease_vol_limit_cb(lv_event_t* ev) {
|
|||||||
instance->ChangeCustomVolume(-2);
|
instance->ChangeCustomVolume(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Headphones::Headphones(drivers::NvsStorage& nvs)
|
Headphones::Headphones(models::TopBar& bar, drivers::NvsStorage& nvs)
|
||||||
: MenuScreen("Headphones"), nvs_(nvs), custom_limit_(0) {
|
: MenuScreen(bar, "Headphones"), nvs_(nvs), custom_limit_(0) {
|
||||||
uint16_t reference = drivers::wm8523::kLineLevelReferenceVolume;
|
uint16_t reference = drivers::wm8523::kLineLevelReferenceVolume;
|
||||||
index_to_level_.push_back(reference - (10 * 4));
|
index_to_level_.push_back(reference - (10 * 4));
|
||||||
index_to_level_.push_back(reference + (6 * 4));
|
index_to_level_.push_back(reference + (6 * 4));
|
||||||
@@ -377,8 +380,10 @@ static auto brightness_str(uint_fast8_t percent) -> std::string {
|
|||||||
return std::to_string(percent) + "%";
|
return std::to_string(percent) + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
Appearance::Appearance(drivers::NvsStorage& nvs, drivers::Display& display)
|
Appearance::Appearance(models::TopBar& bar,
|
||||||
: MenuScreen("Appearance"), nvs_(nvs), display_(display) {
|
drivers::NvsStorage& nvs,
|
||||||
|
drivers::Display& display)
|
||||||
|
: MenuScreen(bar, "Appearance"), nvs_(nvs), display_(display) {
|
||||||
lv_obj_t* toggle_container = settings_container(content_);
|
lv_obj_t* toggle_container = settings_container(content_);
|
||||||
lv_obj_t* toggle_label = lv_label_create(toggle_container);
|
lv_obj_t* toggle_label = lv_label_create(toggle_container);
|
||||||
lv_obj_set_flex_grow(toggle_label, 1);
|
lv_obj_set_flex_grow(toggle_label, 1);
|
||||||
@@ -417,7 +422,8 @@ auto Appearance::CommitBrightness() -> void {
|
|||||||
nvs_.ScreenBrightness(current_brightness_);
|
nvs_.ScreenBrightness(current_brightness_);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputMethod::InputMethod() : MenuScreen("Input Method") {
|
InputMethod::InputMethod(models::TopBar& bar)
|
||||||
|
: MenuScreen(bar, "Input Method") {
|
||||||
lv_obj_t* wheel_label = lv_label_create(content_);
|
lv_obj_t* wheel_label = lv_label_create(content_);
|
||||||
lv_label_set_text(wheel_label, "What does the wheel do?");
|
lv_label_set_text(wheel_label, "What does the wheel do?");
|
||||||
lv_obj_t* wheel_dropdown = lv_dropdown_create(content_);
|
lv_obj_t* wheel_dropdown = lv_dropdown_create(content_);
|
||||||
@@ -431,7 +437,7 @@ InputMethod::InputMethod() : MenuScreen("Input Method") {
|
|||||||
lv_group_add_obj(group_, buttons_dropdown);
|
lv_group_add_obj(group_, buttons_dropdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::Storage() : MenuScreen("Storage") {
|
Storage::Storage(models::TopBar& bar) : MenuScreen(bar, "Storage") {
|
||||||
label_pair(content_, "Storage Capacity:", "32 GiB");
|
label_pair(content_, "Storage Capacity:", "32 GiB");
|
||||||
label_pair(content_, "Currently Used:", "6 GiB");
|
label_pair(content_, "Currently Used:", "6 GiB");
|
||||||
label_pair(content_, "DB Size:", "1.2 MiB");
|
label_pair(content_, "DB Size:", "1.2 MiB");
|
||||||
@@ -446,7 +452,8 @@ Storage::Storage() : MenuScreen("Storage") {
|
|||||||
lv_group_add_obj(group_, reset_btn);
|
lv_group_add_obj(group_, reset_btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
FirmwareUpdate::FirmwareUpdate() : MenuScreen("Firmware Update") {
|
FirmwareUpdate::FirmwareUpdate(models::TopBar& bar)
|
||||||
|
: MenuScreen(bar, "Firmware Update") {
|
||||||
label_pair(content_, "ESP32 FW:", "vIDKLOL");
|
label_pair(content_, "ESP32 FW:", "vIDKLOL");
|
||||||
label_pair(content_, "SAMD21 FW:", "vIDKLOL");
|
label_pair(content_, "SAMD21 FW:", "vIDKLOL");
|
||||||
|
|
||||||
@@ -461,7 +468,7 @@ FirmwareUpdate::FirmwareUpdate() : MenuScreen("Firmware Update") {
|
|||||||
lv_group_add_obj(group_, flash_samd_btn);
|
lv_group_add_obj(group_, flash_samd_btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
About::About() : MenuScreen("About") {
|
About::About(models::TopBar& bar) : MenuScreen(bar, "About") {
|
||||||
lv_obj_t* label = lv_label_create(content_);
|
lv_obj_t* label = lv_label_create(content_);
|
||||||
lv_label_set_text(label, "Some licenses or whatever");
|
lv_label_set_text(label, "Some licenses or whatever");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "font/lv_symbol_def.h"
|
#include "font/lv_symbol_def.h"
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
#include "misc/lv_anim.h"
|
#include "misc/lv_anim.h"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "screen_menu.hpp"
|
#include "screen_menu.hpp"
|
||||||
|
|
||||||
#include "core/lv_event.h"
|
#include "core/lv_event.h"
|
||||||
@@ -59,6 +60,7 @@ static void item_select_cb(lv_event_t* ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TrackBrowser::TrackBrowser(
|
TrackBrowser::TrackBrowser(
|
||||||
|
models::TopBar& top_bar_model,
|
||||||
std::weak_ptr<database::Database> db,
|
std::weak_ptr<database::Database> db,
|
||||||
const std::pmr::string& title,
|
const std::pmr::string& title,
|
||||||
std::future<database::Result<database::IndexRecord>*>&& initial_page)
|
std::future<database::Result<database::IndexRecord>*>&& initial_page)
|
||||||
@@ -83,7 +85,7 @@ TrackBrowser::TrackBrowser(
|
|||||||
.show_back_button = true,
|
.show_back_button = true,
|
||||||
.title = title,
|
.title = title,
|
||||||
};
|
};
|
||||||
auto top_bar = CreateTopBar(content_, config);
|
auto top_bar = CreateTopBar(content_, config, top_bar_model);
|
||||||
back_button_ = top_bar->button();
|
back_button_ = top_bar->button();
|
||||||
|
|
||||||
list_ = lv_list_create(content_);
|
list_ = lv_list_create(content_);
|
||||||
|
|||||||
+24
-50
@@ -54,8 +54,9 @@ std::shared_ptr<Screen> UiState::sCurrentScreen;
|
|||||||
std::shared_ptr<Modal> UiState::sCurrentModal;
|
std::shared_ptr<Modal> UiState::sCurrentModal;
|
||||||
|
|
||||||
models::Playback UiState::sPlaybackModel;
|
models::Playback UiState::sPlaybackModel;
|
||||||
|
models::TopBar UiState::sTopBarModel{{},
|
||||||
bindey::property<battery::Battery::BatteryState> UiState::sPropBatteryState;
|
UiState::sPlaybackModel.is_playing,
|
||||||
|
UiState::sPlaybackModel.current_track};
|
||||||
|
|
||||||
auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool {
|
auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool {
|
||||||
// Init LVGL first, since the display driver registers itself with LVGL.
|
// Init LVGL first, since the display driver registers itself with LVGL.
|
||||||
@@ -75,7 +76,6 @@ void UiState::PushScreen(std::shared_ptr<Screen> screen) {
|
|||||||
sScreens.push(sCurrentScreen);
|
sScreens.push(sCurrentScreen);
|
||||||
}
|
}
|
||||||
sCurrentScreen = screen;
|
sCurrentScreen = screen;
|
||||||
UpdateTopBar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiState::PopScreen() {
|
void UiState::PopScreen() {
|
||||||
@@ -84,7 +84,6 @@ void UiState::PopScreen() {
|
|||||||
}
|
}
|
||||||
sCurrentScreen = sScreens.top();
|
sCurrentScreen = sScreens.top();
|
||||||
sScreens.pop();
|
sScreens.pop();
|
||||||
UpdateTopBar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiState::react(const system_fsm::KeyLockChanged& ev) {
|
void UiState::react(const system_fsm::KeyLockChanged& ev) {
|
||||||
@@ -93,14 +92,8 @@ void UiState::react(const system_fsm::KeyLockChanged& ev) {
|
|||||||
: std::shared_ptr<TouchWheelEncoder>());
|
: std::shared_ptr<TouchWheelEncoder>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiState::react(const system_fsm::BatteryStateChanged&) {
|
void UiState::react(const system_fsm::BatteryStateChanged& ev) {
|
||||||
if (!sServices) {
|
sTopBarModel.battery_state.set(ev.new_state);
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto state = sServices->battery().State();
|
|
||||||
if (state) {
|
|
||||||
sPropBatteryState.set(*state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiState::react(const audio::PlaybackStarted&) {
|
void UiState::react(const audio::PlaybackStarted&) {
|
||||||
@@ -117,34 +110,11 @@ void UiState::react(const audio::PlaybackUpdate& ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UiState::react(const audio::QueueUpdate&) {
|
void UiState::react(const audio::QueueUpdate&) {
|
||||||
ESP_LOGI(kTag, "current changed!");
|
|
||||||
auto& queue = sServices->track_queue();
|
auto& queue = sServices->track_queue();
|
||||||
sPlaybackModel.current_track.set(queue.GetCurrent());
|
sPlaybackModel.current_track.set(queue.GetCurrent());
|
||||||
sPlaybackModel.upcoming_tracks.set(queue.GetUpcoming(10));
|
sPlaybackModel.upcoming_tracks.set(queue.GetUpcoming(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiState::UpdateTopBar() {
|
|
||||||
auto battery_state = sServices->battery().State();
|
|
||||||
bool has_queue = sServices->track_queue().GetCurrent().has_value();
|
|
||||||
bool is_playing = audio::AudioState::is_in_state<audio::states::Playback>();
|
|
||||||
|
|
||||||
widgets::TopBar::State state{
|
|
||||||
.playback_state = widgets::TopBar::PlaybackState::kIdle,
|
|
||||||
.battery_percent = static_cast<uint_fast8_t>(
|
|
||||||
battery_state.has_value() ? battery_state->percent : 100),
|
|
||||||
.is_charging = !battery_state.has_value() || battery_state->is_charging,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (has_queue) {
|
|
||||||
state.playback_state = is_playing ? widgets::TopBar::PlaybackState::kPlaying
|
|
||||||
: widgets::TopBar::PlaybackState::kPaused;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sCurrentScreen) {
|
|
||||||
sCurrentScreen->UpdateTopBar(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace states {
|
namespace states {
|
||||||
|
|
||||||
void Splash::exit() {
|
void Splash::exit() {
|
||||||
@@ -242,7 +212,8 @@ void Browse::entry() {
|
|||||||
if (!db) {
|
if (!db) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sCurrentScreen = std::make_shared<screens::Menu>(db->GetIndexes());
|
sCurrentScreen =
|
||||||
|
std::make_shared<screens::Menu>(sTopBarModel, db->GetIndexes());
|
||||||
sBrowseFirstEntry = false;
|
sBrowseFirstEntry = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,7 +224,8 @@ void Browse::react(const system_fsm::StorageMounted& ev) {
|
|||||||
if (!db) {
|
if (!db) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sCurrentScreen = std::make_shared<screens::Menu>(db->GetIndexes());
|
sCurrentScreen =
|
||||||
|
std::make_shared<screens::Menu>(sTopBarModel, db->GetIndexes());
|
||||||
sBrowseFirstEntry = false;
|
sBrowseFirstEntry = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,31 +239,32 @@ void Browse::react(const internal::ShowSettingsPage& ev) {
|
|||||||
std::shared_ptr<screens::Bluetooth> bt_screen;
|
std::shared_ptr<screens::Bluetooth> bt_screen;
|
||||||
switch (ev.page) {
|
switch (ev.page) {
|
||||||
case internal::ShowSettingsPage::Page::kRoot:
|
case internal::ShowSettingsPage::Page::kRoot:
|
||||||
screen.reset(new screens::Settings());
|
screen.reset(new screens::Settings(sTopBarModel));
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kBluetooth:
|
case internal::ShowSettingsPage::Page::kBluetooth:
|
||||||
bt_screen = std::make_shared<screens::Bluetooth>(sServices->bluetooth(),
|
bt_screen = std::make_shared<screens::Bluetooth>(
|
||||||
sServices->nvs());
|
sTopBarModel, sServices->bluetooth(), sServices->nvs());
|
||||||
screen = bt_screen;
|
screen = bt_screen;
|
||||||
bluetooth_screen_ = bt_screen;
|
bluetooth_screen_ = bt_screen;
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kHeadphones:
|
case internal::ShowSettingsPage::Page::kHeadphones:
|
||||||
screen.reset(new screens::Headphones(sServices->nvs()));
|
screen.reset(new screens::Headphones(sTopBarModel, sServices->nvs()));
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kAppearance:
|
case internal::ShowSettingsPage::Page::kAppearance:
|
||||||
screen.reset(new screens::Appearance(sServices->nvs(), *sDisplay));
|
screen.reset(
|
||||||
|
new screens::Appearance(sTopBarModel, sServices->nvs(), *sDisplay));
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kInput:
|
case internal::ShowSettingsPage::Page::kInput:
|
||||||
screen.reset(new screens::InputMethod());
|
screen.reset(new screens::InputMethod(sTopBarModel));
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kStorage:
|
case internal::ShowSettingsPage::Page::kStorage:
|
||||||
screen.reset(new screens::Storage());
|
screen.reset(new screens::Storage(sTopBarModel));
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kFirmwareUpdate:
|
case internal::ShowSettingsPage::Page::kFirmwareUpdate:
|
||||||
screen.reset(new screens::FirmwareUpdate());
|
screen.reset(new screens::FirmwareUpdate(sTopBarModel));
|
||||||
break;
|
break;
|
||||||
case internal::ShowSettingsPage::Page::kAbout:
|
case internal::ShowSettingsPage::Page::kAbout:
|
||||||
screen.reset(new screens::About());
|
screen.reset(new screens::About(sTopBarModel));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (screen) {
|
if (screen) {
|
||||||
@@ -323,7 +296,7 @@ void Browse::react(const internal::RecordSelected& ev) {
|
|||||||
auto query = db->GetPage(&cont.value());
|
auto query = db->GetPage(&cont.value());
|
||||||
std::pmr::string title = record->text().value_or("TODO");
|
std::pmr::string title = record->text().value_or("TODO");
|
||||||
PushScreen(std::make_shared<screens::TrackBrowser>(
|
PushScreen(std::make_shared<screens::TrackBrowser>(
|
||||||
sServices->database(), title, std::move(query)));
|
sTopBarModel, sServices->database(), title, std::move(query)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +309,7 @@ void Browse::react(const internal::IndexSelected& ev) {
|
|||||||
ESP_LOGI(kTag, "selected index %s", ev.index.name.c_str());
|
ESP_LOGI(kTag, "selected index %s", ev.index.name.c_str());
|
||||||
auto query = db->GetTracksByIndex(ev.index, kRecordsPerPage);
|
auto query = db->GetTracksByIndex(ev.index, kRecordsPerPage);
|
||||||
PushScreen(std::make_shared<screens::TrackBrowser>(
|
PushScreen(std::make_shared<screens::TrackBrowser>(
|
||||||
sServices->database(), ev.index.name, std::move(query)));
|
sTopBarModel, sServices->database(), ev.index.name, std::move(query)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browse::react(const internal::BackPressed& ev) {
|
void Browse::react(const internal::BackPressed& ev) {
|
||||||
@@ -354,8 +327,9 @@ static std::shared_ptr<screens::Playing> sPlayingScreen;
|
|||||||
|
|
||||||
void Playing::entry() {
|
void Playing::entry() {
|
||||||
ESP_LOGI(kTag, "push playing screen");
|
ESP_LOGI(kTag, "push playing screen");
|
||||||
sPlayingScreen.reset(new screens::Playing(
|
sPlayingScreen.reset(new screens::Playing(sTopBarModel, sPlaybackModel,
|
||||||
sPlaybackModel, sServices->database(), sServices->track_queue()));
|
sServices->database(),
|
||||||
|
sServices->track_queue()));
|
||||||
PushScreen(sPlayingScreen);
|
PushScreen(sPlayingScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-39
@@ -5,13 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "widget_top_bar.hpp"
|
#include "widget_top_bar.hpp"
|
||||||
|
#include "battery.hpp"
|
||||||
#include "core/lv_group.h"
|
#include "core/lv_group.h"
|
||||||
#include "core/lv_obj.h"
|
#include "core/lv_obj.h"
|
||||||
#include "event_queue.hpp"
|
#include "event_queue.hpp"
|
||||||
#include "extra/layouts/flex/lv_flex.h"
|
#include "extra/layouts/flex/lv_flex.h"
|
||||||
#include "font/lv_symbol_def.h"
|
#include "font/lv_symbol_def.h"
|
||||||
#include "font_symbols.hpp"
|
#include "font_symbols.hpp"
|
||||||
|
#include "model_top_bar.hpp"
|
||||||
#include "themes.hpp"
|
#include "themes.hpp"
|
||||||
|
#include "track.hpp"
|
||||||
#include "ui_events.hpp"
|
#include "ui_events.hpp"
|
||||||
#include "ui_fsm.hpp"
|
#include "ui_fsm.hpp"
|
||||||
#include "widgets/lv_img.h"
|
#include "widgets/lv_img.h"
|
||||||
@@ -34,7 +37,9 @@ static void back_click_cb(lv_event_t* ev) {
|
|||||||
events::Ui().Dispatch(internal::BackPressed{});
|
events::Ui().Dispatch(internal::BackPressed{});
|
||||||
}
|
}
|
||||||
|
|
||||||
TopBar::TopBar(lv_obj_t* parent, const Configuration& config) {
|
TopBar::TopBar(lv_obj_t* parent,
|
||||||
|
const Configuration& config,
|
||||||
|
models::TopBar& model) {
|
||||||
container_ = lv_obj_create(parent);
|
container_ = lv_obj_create(parent);
|
||||||
lv_obj_set_size(container_, lv_pct(100), 20);
|
lv_obj_set_size(container_, lv_pct(100), 20);
|
||||||
lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_ROW);
|
||||||
@@ -54,50 +59,52 @@ TopBar::TopBar(lv_obj_t* parent, const Configuration& config) {
|
|||||||
back_button_ = nullptr;
|
back_button_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
title_ = lv_label_create(container_);
|
lv_obj_t* title_ = lv_label_create(container_);
|
||||||
lv_label_set_text(title_, config.title.c_str());
|
lv_label_set_text(title_, config.title.c_str());
|
||||||
lv_obj_set_flex_grow(title_, 1);
|
lv_obj_set_flex_grow(title_, 1);
|
||||||
|
|
||||||
playback_ = lv_img_create(container_);
|
lv_obj_t* playback = lv_img_create(container_);
|
||||||
battery_ = lv_img_create(container_);
|
|
||||||
charging_ = lv_label_create(container_);
|
bindings_.push_back(model.is_playing.onChangedAndNow([=](bool is_playing) {
|
||||||
|
lv_img_set_src(playback, is_playing ? &kIconPlay : &kIconPause);
|
||||||
|
}));
|
||||||
|
bindings_.push_back(model.current_track.onChangedAndNow(
|
||||||
|
[=](const std::optional<database::TrackId>& id) {
|
||||||
|
if (id) {
|
||||||
|
lv_obj_clear_flag(playback, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(playback, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
lv_obj_t* battery = lv_img_create(container_);
|
||||||
|
lv_obj_t* charging = lv_label_create(container_);
|
||||||
|
|
||||||
|
bindings_.push_back(model.battery_state.onChangedAndNow(
|
||||||
|
[=](const battery::Battery::BatteryState& state) {
|
||||||
|
if (state.is_charging) {
|
||||||
|
lv_label_set_text(charging, "+");
|
||||||
|
} else {
|
||||||
|
lv_label_set_text(charging, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.percent >= 95) {
|
||||||
|
lv_img_set_src(battery, &kIconBatteryFull);
|
||||||
|
} else if (state.percent >= 75) {
|
||||||
|
lv_img_set_src(battery, &kIconBattery80);
|
||||||
|
} else if (state.percent >= 55) {
|
||||||
|
lv_img_set_src(battery, &kIconBattery60);
|
||||||
|
} else if (state.percent >= 35) {
|
||||||
|
lv_img_set_src(battery, &kIconBattery40);
|
||||||
|
} else if (state.percent >= 15) {
|
||||||
|
lv_img_set_src(battery, &kIconBattery20);
|
||||||
|
} else {
|
||||||
|
lv_img_set_src(battery, &kIconBatteryEmpty);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
themes::Theme::instance()->ApplyStyle(container_, themes::Style::kTopBar);
|
themes::Theme::instance()->ApplyStyle(container_, themes::Style::kTopBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto TopBar::Update(const State& state) -> void {
|
|
||||||
switch (state.playback_state) {
|
|
||||||
case PlaybackState::kIdle:
|
|
||||||
lv_img_set_src(playback_, NULL);
|
|
||||||
break;
|
|
||||||
case PlaybackState::kPaused:
|
|
||||||
lv_img_set_src(playback_, &kIconPause);
|
|
||||||
break;
|
|
||||||
case PlaybackState::kPlaying:
|
|
||||||
lv_img_set_src(playback_, &kIconPlay);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.is_charging) {
|
|
||||||
lv_label_set_text(charging_, "+");
|
|
||||||
} else {
|
|
||||||
lv_label_set_text(charging_, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.battery_percent >= 95) {
|
|
||||||
lv_img_set_src(battery_, &kIconBatteryFull);
|
|
||||||
} else if (state.battery_percent >= 75) {
|
|
||||||
lv_img_set_src(battery_, &kIconBattery80);
|
|
||||||
} else if (state.battery_percent >= 55) {
|
|
||||||
lv_img_set_src(battery_, &kIconBattery60);
|
|
||||||
} else if (state.battery_percent >= 35) {
|
|
||||||
lv_img_set_src(battery_, &kIconBattery40);
|
|
||||||
} else if (state.battery_percent >= 15) {
|
|
||||||
lv_img_set_src(battery_, &kIconBattery20);
|
|
||||||
} else {
|
|
||||||
lv_img_set_src(battery_, &kIconBatteryEmpty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|||||||
Reference in New Issue
Block a user