JSON Score
ci / checks (push) Successful in 39m41s

This commit is contained in:
khodowany
2026-09-07 21:12:22 -05:00
parent 9a3ec7caa5
commit 900604b9fb
15 changed files with 1065 additions and 5634 deletions
+116 -3
View File
@@ -11,6 +11,7 @@
#include <utility>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/post.hpp>
#include <luma.hpp>
@@ -22,6 +23,11 @@
namespace {
constexpr auto touch_hold_duration = std::chrono::milliseconds{700};
constexpr auto touch_double_tap_duration = std::chrono::milliseconds{220};
using touch_handler = std::function<std::bool_t(luma::touch_event const&)>;
auto bind_port(vamp_zero::config const& config) -> std::uint16_t {
auto const& bind = config.control.endpoint.bind;
auto colon = bind.rfind(':');
@@ -404,7 +410,7 @@ auto draw_score(luma::draw_context& context, luma::rect bounds, vamp_zero::app_s
class vamp_root_control final : public luma::control {
public:
explicit vamp_root_control(vamp_zero::ui_state state) : state_{std::move(state)} {}
explicit vamp_root_control(vamp_zero::ui_state state, touch_handler on_touch) : state_{std::move(state)}, on_touch_{std::move(on_touch)} {}
auto measure(luma::draw_context&, luma::theme const&, luma::constraints limits) -> luma::size override {
return luma::clamp({.width = 1024.0F, .height = 600.0F}, limits);
}
@@ -438,13 +444,117 @@ public:
draw_main_menu(context, content, state_.app);
}
}
auto handle_touch(luma::touch_event const& event) -> std::bool_t override {
return on_touch_ ? on_touch_(event) : false;
}
private:
vamp_zero::ui_state state_{};
touch_handler on_touch_{};
};
}
vamp_zero::zero_ui::zero_ui(boost::asio::any_io_executor executor, luma::application_config config) : executor_{std::move(executor)}, application_{std::move(config)} {}
vamp_zero::zero_ui::zero_ui(boost::asio::any_io_executor executor, luma::application_config config, vamp_zero::zero_ui::command_handler command_handler)
: executor_{std::move(executor)}, tap_timer_{executor_}, application_{std::move(config)}, command_handler_{std::move(command_handler)} {}
auto vamp_zero::zero_ui::send_touch_command(vamp_protocol::page_command command) -> void {
if (!command_handler_) {
return;
}
boost::asio::post(executor_, [handler = command_handler_, command] {
handler(command);
});
}
auto vamp_zero::zero_ui::cancel_pending_tap_locked() -> void {
pending_tap_ = false;
}
auto vamp_zero::zero_ui::arm_pending_tap() -> void {
tap_timer_.expires_after(touch_double_tap_duration);
tap_timer_.async_wait([this](boost::system::error_code const& error) {
if (error) {
return;
}
auto send_next = false;
{
auto lock = std::scoped_lock{touch_mutex_};
send_next = pending_tap_;
pending_tap_ = false;
}
if (send_next) {
send_touch_command(vamp_protocol::page_command::NEXT);
}
});
}
auto vamp_zero::zero_ui::handle_touch(luma::touch_event const& event) -> std::bool_t {
if (!command_handler_ || event.points.empty()) {
return false;
}
auto consumed = false;
auto commands = std::vector<vamp_protocol::page_command>{};
auto arm_tap = false;
{
auto lock = std::scoped_lock{touch_mutex_};
for (auto const& point : event.points) {
if (point.phase == luma::touch_phase::DOWN && !active_touch_id_) {
active_touch_id_ = point.id;
touch_down_time_ = event.time;
hold_sent_ = false;
tap_timer_.cancel();
consumed = true;
continue;
}
if (!active_touch_id_ || point.id != *active_touch_id_) {
continue;
}
consumed = true;
if (point.phase == luma::touch_phase::CANCEL) {
active_touch_id_.reset();
hold_sent_ = false;
cancel_pending_tap_locked();
tap_timer_.cancel();
continue;
}
if (point.phase == luma::touch_phase::MOVE) {
if (!hold_sent_ && event.time - touch_down_time_ >= touch_hold_duration) {
hold_sent_ = true;
cancel_pending_tap_locked();
tap_timer_.cancel();
commands.push_back(vamp_protocol::page_command::SELECT);
}
continue;
}
if (point.phase == luma::touch_phase::UP) {
active_touch_id_.reset();
if (!hold_sent_ && event.time - touch_down_time_ >= touch_hold_duration) {
commands.push_back(vamp_protocol::page_command::SELECT);
} else if (!hold_sent_) {
if (pending_tap_ && event.time - last_tap_time_ <= touch_double_tap_duration) {
cancel_pending_tap_locked();
tap_timer_.cancel();
commands.push_back(vamp_protocol::page_command::PREVIOUS);
} else {
pending_tap_ = true;
last_tap_time_ = event.time;
arm_tap = true;
}
}
hold_sent_ = false;
}
}
}
for (auto command : commands) {
send_touch_command(command);
}
if (arm_tap) {
arm_pending_tap();
}
return consumed;
}
auto vamp_zero::zero_ui::run() -> std::expected<void, modulus::error> {
auto state = snapshot();
@@ -459,6 +569,7 @@ auto vamp_zero::zero_ui::run() -> std::expected<void, modulus::error> {
}
auto vamp_zero::zero_ui::stop() -> void {
tap_timer_.cancel();
application_.request_stop();
}
@@ -482,7 +593,9 @@ auto vamp_zero::zero_ui::snapshot() const -> vamp_zero::ui_state {
}
auto vamp_zero::zero_ui::make_root(vamp_zero::ui_state const& state) -> std::expected<std::unique_ptr<luma::control>, modulus::error> {
return std::make_unique<vamp_root_control>(state);
return std::make_unique<vamp_root_control>(state, [this](luma::touch_event const& event) {
return handle_touch(event);
});
}
auto vamp_zero::make_ui_state(vamp_zero::config const& config, vamp_zero::app_state app) -> vamp_zero::ui_state {